Elasticsearch многоуровневый вложенный объект фильтр и обновление - PullRequest
1 голос
/ 23 мая 2019

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 голосов
/ 23 мая 2019

Ниже показано, как, глядя на ваш документ, я создал отображение, скрипт обновления по запросу и ответ, как он выглядит.

Отображение:

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

Запрос:

Ниже приведено Обновление по запросу , которое вам потребуется:

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

Надеюсь, это поможет!

...