使用Java API更新ElasticSearch索引中的嵌套字段

时间:2014-04-29 11:47:15

标签: java json elasticsearch

我在弹性搜索上使用Java API进行CRUD操作。

我有一个带嵌套字段的类型,我想更新这个字段。

以下是我的类型映射:

"enduser": {
            "properties": {
                "location": {
                    "type": "nested",
                    "properties":{
                        "point":{"type":"geo_point"}
                    }
                }
            }
        }

当然我的最终用户类型还有其他参数。

现在我想在嵌套字段中添加此文档:

"location":{
          "name": "London",
           "point": "44.5, 5.2"
}

我正在搜索有关如何更新嵌套文档的文档但我无法找到任何内容。例如,我在字符串中有以前的JSON obect(让我们调用这个字符串json)。我尝试了以下代码,但似乎无法正常工作:

params.put("location", json);
client.prepareUpdate(index, ElasticSearchConstants.TYPE_END_USER,id).setScript("ctx._source.location = location").setScriptParams(params).execute().actionGet();

我有来自elasticsearch的解析错误。谁知道我做错了什么?

4 个答案:

答案 0 :(得分:5)

您不需要该脚本,只需更新即可。

    UpdateRequestBuilder br = client.prepareUpdate("index", "enduser", "1");
    br.setDoc("{\"location\":{ \"name\": \"london\", \"point\": \"44.5,5.2\" }}".getBytes());
    br.execute();

答案 1 :(得分:3)

我试图重新创建你的情况,我通过使用.setScript方法的其他方式解决了它。

您的更新请求现在看起来像是:

client.prepareUpdate(index, ElasticSearchConstants.TYPE_END_USER,id).setScript("ctx._source.location =" + json).execute().actionGet()

希望它会对你有所帮助。

答案 2 :(得分:2)

我不确定您使用的是哪个ES版本,但下面的解决方案在2.2.0上完美适用于我。我必须存储有关新闻文章的命名实体的信息。我想如果你希望在你的情况下有多个位置,它也适合你。

这是我想要更新的嵌套对象

"entities" : [
    {
        "disambiguated" : {
            "entitySubTypes" : [],
            "disambiguatedName" : "NameX"
        },
        "frequency" : 1,
        "entityType" : "Organization",
        "quotations" : ["...", "..."],
        "name" : "entityX"
    },
    {
        "disambiguated" : {
            "entitySubType" : ["a",  "b" ],
            "disambiguatedName" : "NameQ"
        },
        "frequency" : 5,
        "entityType" : "secondTypeTest",
        "quotations" : [ "...", "..."],
        "name" : "entityY"
    }
],

这是代码

UpdateRequest updateRequest = new UpdateRequest();
updateRequest.index(indexName);
updateRequest.type(mappingName);
updateRequest.id(url); // docID is a url
XContentBuilder jb = XContentFactory.jsonBuilder();
jb.startObject(); // article
jb.startArray("entities"); // multiple entities

for ( /*each namedEntity*/) {

jb.startObject() // entity
   .field("name", name)
   .field("frequency",n)
   .field("entityType", entityType)
   .startObject("disambiguated") // disambiguation
   .field("disambiguatedName", disambiguatedNameStr)
   .field("entitySubTypes", entitySubTypeArray) // multi value field
   .endObject() // disambiguation
   .field("quotations", quotationsArray) // multi value field
   .endObject(); // entity

}

jb.endArray(); // array of nested objects
b.endObject(); // article
updateRequest.doc(jb);

Blblblblblblbl的答案对我来说无效,因为我们的服务器中没有启用脚本。我还没有尝试Bask的答案 - Alcanzar给了我一个艰难的时间,因为我认为无法正确配制setDoc收到的json字符串。我经常遇到错误,我要么使用对象而不是字段,反之亦然。我还尝试用指示here的doc {}包装json字符串,但我没有设法让它工作。正如您所提到的,很难理解如何在ES的Java API中制定curl语句。

答案 3 :(得分:1)

使用Java API更新arraylist和object值的简单方法。

UpdateResponse update = client.prepareUpdate("indexname","type",""+id)
        .addScriptParam("param1", arrayvalue)
         .addScriptParam("param2", objectvalue)
        .setScript("ctx._source.field1=param1;ctx._source.field2=param2").execute()
                .actionGet(); 

arrayvalue-[
{
    "text": "stackoverflow",
    "datetime": "2010-07-27T05:41:52.763Z",
    "obj1": {
        "id": 1,
        "email": "sa@gmail.com",
        "name": "bass"
        },
    "id": 1,
}

object value -
"obj1": {
    "id": 1,
    "email": "sa@gmail.com",
    "name": "bass"
}