эластичный поиск: проверка наличия двух значений (term) в одном и том же поле (вложенном) не дает результата (с одним значением дает результаты)

#elasticsearch #match #term

#elasticsearch #совпадение

Вопрос:

У меня проблема с ES, когда я пытаюсь проверить наличие 2 (или 2) значений; которые существуют во вложенном документе.

Сначала данные, которые я ввел в ES, а затем точный случай, который не сработал.

Сопоставление

 POST /test
{
   "mappings": {
      "doc": {
         "properties": {
            "attributes": {
               "type": "nested"
            }
         }
      }
   }
}
 

Тестовые данные

 POST /test/doc/1 { "attributes": [{"id": 1}, {"id": 2}, {"id": 3}] }
POST /test/doc/2 { "attributes": [{"id": 3}, {"id": 5}] }
POST /test/doc/3 { "attributes": [{"id": 5}] }
 

Запрос

 POST /test/doc/_search
{
   "query": {
      "nested": {
         "path": "attributes",
         "query": {
            "constant_score": {
               "filter": {
                  "bool": {
                     "must": [
                        {
                           "term": {
                              "attributes.id": 3
                           }
                        }
                     ]
                  }
               }
            }
         }
      }
   }
}
 

Результат, который работает (запрошен только один атрибут)

 {
   "took": 3,
   "timed_out": false,
   "_shards": {
      "total": 5,
      "successful": 5,
      "failed": 0
   },
   "hits": {
      "total": 2,
      "max_score": 1,
      "hits": [
         {
            "_index": "test",
            "_type": "doc",
            "_id": "2",
            "_score": 1,
            "_source": {
               "attributes": [
                  {
                     "id": 3
                  },
                  {
                     "id": 5
                  }
               ]
            }
         },
         {
            "_index": "test",
            "_type": "doc",
            "_id": "1",
            "_score": 1,
            "_source": {
               "attributes": [
                  {
                     "id": 1
                  },
                  {
                     "id": 2
                  },
                  {
                     "id": 3
                  }
               ]
            }
         }
      ]
   }
}
 

теперь я пытаюсь проверить 2 идентификатора атрибута и получаю пустой результат

Запрос (2 атрибута)

 POST /test/doc/_search
{
   "query": {
      "nested": {
         "path": "attributes",
         "query": {
            "constant_score": {
               "filter": {
                  "bool": {
                     "must": [
                        {
                           "term": {
                              "attributes.id": 3
                           }
                        },
                        {
                           "term": {
                              "attributes.id": 5
                           }
                        }
                     ]
                  }
               }
            }
         }
      }
   }
}
 

Результат

 {
   "took": 2,
   "timed_out": false,
   "_shards": {
      "total": 5,
      "successful": 5,
      "failed": 0
   },
   "hits": {
      "total": 0,
      "max_score": null,
      "hits": []
   }
}
 

Как и в результате в одном запросе, я получил документ с идентификаторами атрибутов 3 и 5. Теперь у меня пустой результат.

Редактировать:

решением моей проблемы было не использовать вложенный объект!

 POST /test
{
   "mappings": {
      "doc": {
         "properties": {
            "attributes": {
               "type": "integer"
            }
         }
      }
   }
}


POST /test/doc/1 
{ "attributes": [1, 2, 3] }
POST /test/doc/2 
{ "attributes": [3, 5] }
POST /test/doc/3
{ "attributes": [5] }

POST /test/doc/_search
{
   "query": {
      "bool": {
         "must": [
            {
               "term": {
                  "attributes": 3
               }
            },
            {
               "term": {
                  "attributes": 5
               }
            }
         ]
      }
   }
}
 

Ответ №1:

Это правильное поведение вложенных объектных отношений. Вложенные сопоставления сообщают, что вложенный объект индексируется как отдельные скрытые документы, и запрос выполняется для каждого вложенного объекта, а не для всей коллекции. Вы сказали в своем запросе, что найдите мне атрибут, где id = 3 и id = 5. Честно говоря, сценарий заключается в том, чтобы лучше взглянуть на отображение внутреннего объекта. В этой статье дается объяснение, когда следует использовать внутренний объект и вложенный объект, на основе очень похожего примера: https://www.elastic.co/guide/en/elasticsearch/guide/current/nested-objects.html

Ниже вы можете найти информацию о том, как хранятся данные для внутреннего объекта и для вложенного объекта. Часто люди используют вложенное сопоставление для сбора данных, но не знают последствий этого решения, поэтому я думаю, вам следует пересмотреть свой подход.

Внутренний объект сгенерирует что-то вроде этого:

 attributes.id [1,2,3]
attributes.id [3,5]
attributes.id [5]
 

вложенный будет генерировать что-то вроде этого:

 attributes.id [{"id": 1}, {"id": 2}, {"id": 3}]
attributes.id [{"id": 3}, {"id": 5}] 
attributes.id [{"id": 5}]