【问题标题】:Elasticsearch multilevel nested object filter and updateElasticsearch 多级嵌套对象过滤和更新
【发布时间】:2019-05-23 09:59:50
【问题描述】:

弹性搜索: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,

      },

   }
]
} 

在这里,我们有多家商店,每家商店都有多本书。对于每本书,我们每天都存储用户 cmets。我想通过检查该特定日期的评论是否已经存在来在 [BookInfo.Comments] 下添加日期和评论。如果它已经存在,那么我需要跳过它,如果没有,然后附加新的评论。 我尝试通过更新 API 来做到这一点,但我无法过滤特定书籍并从可用书籍列表中更新它的 cmets。有人可以帮我弄这个吗?提前致谢。

【问题讨论】:

    标签: elasticsearch nested kibana elasticsearch-painless


    【解决方案1】:

    请参阅下面的内容,查看您有问题的文档,我如何创建映射、通过查询脚本更新以及响应的显示方式。

    映射:

    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"
          }
        ]
      }
    }
    

    希望这会有所帮助!

    【讨论】:

    • 非常感谢您的回复。但是是否可以使用批量 API 对其进行更新?
    • 通过查询更新或多或少,更新类似于引擎盖下的批量。它不适用于Bulk API
    • 所以我不能批量使用 update_by_query。现在我用更新改变了查询。现在是否可以通过将 storeID 作为参数传递而轻松无痛。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-18
    • 2020-07-24
    • 1970-01-01
    相关资源
    最近更新 更多