使用Java在Elasticsearch中进行Update By Query操作

11

我目前正在使用Elasticsearch V2.3.1。我想在Java中使用以下的Elasticsearch查询。

POST /twitter/_update_by_query
{
  "script": {
    "inline": "ctx._source.List = [‘Item 1’,’Item 2’]”
  },
  "query": {
    "term": {
      "user": "kimchy"
    }
  }
}
上述查询搜索名为“kimchy”的“user”,并使用给定的值更新“List”字段。此查询同时更新多个文档。 我在这里阅读了关于Java的Update API:https://www.elastic.co/guide/en/elasticsearch/client/java-api/2.3/java-docs-update.html,但未找到我想要的内容。 Java的Update API仅介绍如何一次更新单个文档。是否有任何方法可以更新多个文档?如果我缺少明显的信息,请原谅。感谢您的时间。
更新: 我尝试了以下Java代码:
Client client = TransportClient.builder().addPlugin(ReindexPlugin.class)
    .build().addTransportAddress(new InetSocketTransportAddress(
        InetAddress.getByName("127.0.0.1"), 9300));

UpdateByQueryRequestBuilder ubqrb = UpdateByQueryAction.INSTANCE
    .newRequestBuilder(client);

Script script = new Script("ctx._source.List = [\"Item 1\",\"Item 2\"]");

//termQuery is not recognised by the program
BulkIndexByScrollResponse r = ubqrb.source("twitter").script(script)
    .filter(termQuery("user", "kimchy")).execute().get();

所以我按照上面的方式编辑了Java程序,但是Java没有识别termQuery。请问我在这里做错了什么?谢谢。

2个回答

16

自ES 2.3版本开始,通过查询更新功能可以作为REST端点_update_by_query使用,但Java客户端不支持。要从您的Java客户端代码调用此端点,您需要在pom.xml中包含reindex模块,像这样:


<dependency>
    <groupId>org.elasticsearch.module</groupId>
    <artifactId>reindex</artifactId>
    <version>2.3.2</version>
</dependency>

然后在构建客户端时需要包含此模块:

clientBuilder.addPlugin(ReindexPlugin.class);

最后你可以像这样调用它:

UpdateByQueryRequestBuilder ubqrb = UpdateByQueryAction.INSTANCE.newRequestBuilder(client);

Script script = new Script("ctx._source.List = [\"Item 1\",\"Item 2\"]");

BulkIndexByScrollResponse r = ubqrb.source("twitter")
    .script(script)
    .filter(termQuery("user", "kimchy"))
    .get();

更新

如果您需要指定更新应关注的类型,可以这样做:

ubqrb.source("twitter").source().setTypes("type1");
BulkIndexByScrollResponse r = ubqrb.script(script)
    .filter(termQuery("user", "kimchy"))
    .get();

2
你需要添加 import static org.elasticsearch.index.query.QueryBuilders.termQuery; - Val
嗨@Val,它有效了,但是这种方式(在BulkIndexByScrollResponse中使用过滤器)只能更新一个用户名为“Kimchy”的文档。是否可以使用setQuery在BulkIndexByScrollResponse中更新多个文档?或者可能有其他方法吗? - A Coder Gamer
当然,你可以编写任何类型的查询。那只是一个例子。你的查询是什么? - Val
@ Val,你能描述一下clientBuilder是什么类型以及如何获取它吗?非常感谢。 - Adam Libuša
1
对于那些使用 ES 版本 5.5.0 或类似版本的人提供一个提示:插件必须作为 PreBuiltTransportClient 构造函数的第二个参数添加。 - Adam Libuša
显示剩余8条评论

3
在ES 7.9中, 使用UpdateByQueryRequest也可以实现此功能。
Map<String, Object> map = new HashMap<String, Object>();

UpdateByQueryRequest updateByQueryRequest = new UpdateByQueryRequest("indexName");
updateByQueryRequest.setConflicts("proceed");
updateByQueryRequest.setQuery(new TermQueryBuilder("_id", documentId));
Script script = new Script(ScriptType.INLINE, "painless",
        "ctx._source = params", map);
updateByQueryRequest.setScript(script);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接