Elasticsearch多级嵌套对象过滤器和更新

时间:2019-05-23 09:59:51

标签: elasticsearch nested kibana elasticsearch-painless

Elasticsearch:6.3
我正在尝试通过过滤特定的书来更新嵌套字段。下面是示例记录。

{  
   "StoreName":"test",
   "StoreID":"12435",
   "BookInfo":[  
      {  
         "Name":"Book1",
         "Comments":[  
            {  
               "date":"2019-01-07",
               "Comment":"this is a nice book"
            },
            {  
               "date":"2019-01-06",
               "Comment":"this is a nice book"
            },
            {  
               "date":"2019-01-04",
               "Comment":"this is a nice book"
            },
            {  
               "date":"2019-01-03",
               "Comment":"this is a nice book"
            }
         ],
         "UPC":2435466,

      },
      {  
         "Name":"Book2",
         "Comments":[  
            {  
               "date":"2019-01-07",
               "Comment":"this is a nice book"
            },
            {  
               "date":"2019-01-06",
               "Comment":"this is a nice book"
            },
            {  
               "date":"2019-01-04",
               "Comment":"this is a nice book"
            },
            {  
               "date":"2019-01-03",
               "Comment":"this is a nice book"
            }
         ],
         "UPC":576868345657,

      },

   }
]
} 

在这里,我们有多家商店,每家商店都有多本图书。对于每本书,我们每天都会存储用户评论。我想通过检查特定日期的评论是否已经存在来在[BookInfo.Comments]下添加日期和评论。如果已经存在,那么我需要跳过它,然后添加新评论。 我尝试通过更新API来执行此操作,但无法过滤特定的书并从可用书的列表中更新它的注释。有人可以帮我弄这个吗?预先感谢。

1 个答案:

答案 0 :(得分:0)

请查看下面的内容,查看所涉及的文档,我已经创建了映射,按查询脚本进行的更新以及响应的显示方式。

映射:

PUT mybook
{
  "mappings": {
    "mydocs":{
      "properties":{
        "StoreName": {
          "type": "keyword"
        },
        "StoreID":{
          "type": "keyword"
        },
        "BookInfo":{
          "type": "nested",
          "properties": {
            "Comments" :{
              "type": "nested",
              "properties":{
                "date":{
                  "type": "date"
                },
                "Comment": {
                  "type": "text"
                }
              }
            },
            "Name": {
              "type": "keyword"
            }
          }
        }
      }
    }
  }
}

查询:

下面是您需要的Update By Query

POST mybook/_update_by_query
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "StoreName": "test"
          }
        },
        {
          "term": {
            "StoreID": "12435"
          }
        },
        {
          "nested": {
            "path": "BookInfo",
            "query": {
              "term": {
                "BookInfo.Name": "Book1"
              }
            }
          }
        }
      ]
    }
  },
  "script": {
    "lang": "painless",
    "inline": """
      ArrayList list = ctx._source.BookInfo;
      for(int i=0; i<list.size();i++){
        HashMap myHashMap = list.get(i);
        boolean isPresent = false;
        for(int j=0; j<myHashMap.size();j++){
          String mybook = myHashMap.get(params.book_key);
          if(mybook==params.book_value)
          {
            ArrayList mylist = myHashMap.get("Comments");
            for(int k=0; k<mylist.size(); k++){
              HashMap existingMap = mylist.get(k);
              Iterator entries = existingMap.entrySet().iterator();
              while(entries.hasNext()){
                Map.Entry entry = (Map.Entry) entries.next();
                if(entry.getKey()==params.date_key && entry.getValue()==params.date_value){
                  isPresent = true
                }
              }  
            }

            if(!isPresent){
              HashMap myMap = new HashMap();
              myMap.put(params.date_key, params.date_value);
              myMap.put(params.comment_key, params.comment_value);
              mylist.add(myMap);
              isPresent = false;
            }
          }
        }
      }
    """,
    "params": {
      "book_key":   "Name",
      "book_value": "Book1",
      "date_key":   "date",
      "date_value": "2019-01-08",
      "comment_key": "Comment",
      "comment_value": "This is a new comment here"

  }}
}

总而言之,我正在尝试为具有"Name:Book1""StoreId": "1234""StoreName": "test"的书添加日期和评论

请注意查询中的以下部分:

"params": {
      "book_key":   "Name",
      "book_value": "Book1",
      "date_key":   "date",
      "date_value": "2019-01-08",
      "comment_key": "Comment",
      "comment_value": "This is a new comment here"

}

这些是您需要修改(根据您的要求)以运行上述查询的参数。

我建议您轻松进行脚本编写,就像编写简单的Java代码一样,我只是从BookInfo遍历它,以到达有问题的所需文档/字段,添加date/comment

当然,请原谅我使用了如此多的迭代和循环。我建议更好的方法是在您的应用程序层中完全构建文档并重新输入文档。

响应:

{
  "_index": "mybook",
  "_type": "mydocs",
  "_id": "1",
  "_version": 44,
  "found": true,
  "_source": {
    "StoreName": "test",
    "StoreID": "12435",
    "BookInfo": [
      {
        "Comments": [
          {
            "date": "2019-01-07",
            "Comment": "this is a nice book"
          },
          {
            "date": "2019-01-06",
            "Comment": "this is a nice book"
          },
          {
            "date": "2019-01-04",
            "Comment": "this is a nice book"
          },
          {
            "date": "2019-01-03",
            "Comment": "this is a nice book"
          },
          {
            "date": "2019-01-08",
            "Comment": "This is a new comment here"
          }
        ],
        "UPC": 2435466,
        "Name": "Book1"
      },
      {
        "Comments": [
          {
            "date": "2019-01-07",
            "Comment": "this is a nice book"
          },
          {
            "date": "2019-01-06",
            "Comment": "this is a nice book"
          },
          {
            "date": "2019-01-04",
            "Comment": "this is a nice book"
          },
          {
            "date": "2019-01-03",
            "Comment": "this is a nice book"
          }
        ],
        "UPC": 576868345657,
        "Name": "Book2"
      }
    ]
  }
}

希望这会有所帮助!