ElasticSearch:更新数组中的嵌套文档

时间:2014-08-18 10:51:00

标签: elasticsearch

鉴于文件

curl -XPUT 'localhost:9200/test/me/here' -d '{
  "top" : [
    { "searchkey" : "change"},
    { "searchkey" : "keep"}
  ]
}'

我需要一个更新查询,它会将新字段添加到searchkey等于change的子文档中,并保持其他任何子文档的完整性。然后是预期的结果:

{
  "top" : [
    { "searchkey" : "change", "newfield" : "newvalue"},
    { "searchkey" : "keep"}
  ]
}

运行通过索引选择内部文档的查询工作,但我不提前知道内部顺序,而且它非常脆弱:

curl -XPOST 'localhost:9200/test/me/here/_update' -d '{
    "script" : "ctx._source.top[0].newfield = v",
    "params" : {
      "v" : "newvalue"
    }
}'

有没有办法告诉ES将新字段添加到符合某些条件的内部文档?类似的东西:

curl -XPOST 'localhost:9200/test/me/here/_update' -d '{
    "script" : "ctx._source.top[ctx._source.top.searchkey == s].newfield = v",
    "params" : {
      "s" : "change",
      "v" : "newvalue"
    }
}'

或者,如果我删除数组并将文档转换为:

,我会做得更好并且省去一些头疼吗?
{
"change" : {},
"keep" : {}
}

2 个答案:

答案 0 :(得分:3)

您可以将更新与脚本一起使用。见例:

PUT test/data/3/
{
   "source": [
     {
       "name": "A",
       "count": 1
     },
     {
       "name": "B",
       "count": 2
     },
     {
       "name": "c",
       "count": 3
     }
   ]
}

GET test/data/3

POST test/data/3/_update
{
 "script": " for (int i = 0; i < source.size(); i++) {boolean f = false;for (int j = 0; j < ctx._source.source.size(); j++) {if (ctx._source.source[j].name == source[i].name) {ctx._source.source[j].count = source[i].count;f=true;break;}}\nif(!f){ctx._source.source.add(source[i]);}}",
 "params": {
   "source": [
     {
       "name": "A",
       "count": 10
     },
     {
       "name": "B",
       "count": 30
     },
     {
       "name": "D",
       "count": 50
     }
   ]
 }
}

GET test/data/3

答案 1 :(得分:0)

我们可以使用update_by_query API获取与条件匹配的文档,然后滚动json数组以更新数组中的对象。

POST test/data/_update_by_query
{
    "script": {
        "lang":"painless",
        "source":"""
            for(int i=0;i<ctx._source.top.length;i++){
                if(ctx._source.top[i].searchkey == params.match_value){
                    ctx._source.top[i].new_field = params.new_value;
                }
            }
        """,
        "params" : {
             "match_value" : "change",
             "new_value" : "new_value"
         }
    },
    "query" : {
        "match" : {
            "top.searchkey": "change"
        }
    }

}