Фильтр вложенных объектов Elasticsearch


Я новичок в Elasticsearch и пытаюсь создать фильтр для извлечения документов, имеющих определенные атрибуты.

Атрибуты определяются как вложенные объекты в отображении следующим образом:

"attributes": {
  "type": "nested",
    "properties" : {
      "id": {
        "type": "integer"
      },
      ...
    }
  }
}

Я пытаюсь выполнить сложный запрос в виде:

(attribute.id == 1 OR attribute.id == 2) AND (attribute.id == 3 OR attribute.id == 4)

В соответствии с тем, что я прочитал до сих пор, я создал следующий запрос к es:

{
  "query": {
    "filtered": {
     "query": {
        "match_all": {}
     },
     "filter": {
        "nested": {
           "path": "attributes",
           "filter": {
              "bool": {
                "must": [
                    { "bool" : {
                      "should" : [
                        { "term": { "attributes.id": 1 }},
                        { "term": { "attributes.id": 2 }}
                      ]
                    }},
                    { "bool" : {
                      "should" : [
                        { "term": { "attributes.id": 3 }},
                        { "term": { "attributes.id": 4 }}
                      ]
                    }}
                ]
              }
           }
        }
     }
  }
},
"sort": {
    "date": { "order": "desc" }
  }
}

Однако это не возвращает никаких результатов. Если я удаляю один из двух bools в блоке must, он фильтрует документы правильно.

Та же проблема существует (без результатов), если я изменю запрос (в целях тестирования) на:

"must": [
  { "term": { "attributes.id": 3 }},
  { "bool" : {
    "should" : [
      { "term": { "attributes.id": 1 }},
      { "term": { "attributes.id": 2 }}
    ]
  }}
]

Что в моем понимании переводится как attributes.id == 3 AND (attributes.id == 1 OR attributes.id == 2)

Это elasticsearch 2.x. что я делаю не так?

1 4

1 ответ:

Чтобы получить результаты, которые вы ищете, вам нужно будет выполнить два отдельных запроса nested и связать их вместе с запросом bool.

Вот пример:

{
  "bool":{
    "must":[
      {
        "nested":{
          "path":"attributes",
          "filter":{
            "bool":{
              "should":[
                { "term": {"attributes.id": 1 }},
                { "term": {"attributes.id": 2 }}
              ]
            }
          }
        }
      },
      {
        "nested":{
          "path":"attributes",
          "filter":{
            "bool":{
              "should":[
                { "term": {"attributes.id": 3 }},
                { "term": {"attributes.id": 4 }}
              ]
            }
          }
        }
      }
    ]
  }
}

Причина этого кроется в тонком нюансе с вложенными документами и вложенными запросами. Взгляните на ту часть документации по вложенным запросам , которая гласит:

Запрос выполняется к вложенным объектам / docs, как если бы они были проиндексированы как отдельные документы (они, внутренне) и в результате чего корневой Родительский документ (или родительское вложенное отображение).

При выполнении запроса nested вы фактически не выполняете запрос к корневому документу (хотя он чувствует таким образом). Запрос работает с вложенными документами , как если бы они были отдельными документами.

Таким образом, при запросе вложенного документа , имеющего как id=(1 или 2), так и id=(3 или 4), Вы не получаете результатов. Каждый вложенный документ, в ваши данные, похоже, имеют только одно из этих значений идентификатора.