Данные массива ElasticSearch соответствуют нескольким свойствам во вложенном элементе с условием И - PullRequest
0 голосов
/ 03 августа 2020

Я столкнулся с проблемой, когда у меня есть два документа, каждый из которых содержит массив объектов. Мне нравится искать один документ, содержащий два свойства для вложенного объекта (совпадающие с обоими одновременно в одном объекте), но я всегда получаю оба документа.

Я создал документы с помощью:

POST /respondereval/_doc
{
  "resp_id": "1236",
  "responses": [
     {"key": "meta","text":"abc"},
     {"key": "property 1", "text": "yes"},
     {"key": "property 2", "text": "yes"},
  ]
}

POST /respondereval/_doc
{
  "resp_id": "1237",
  "responses": [
     {"key": "meta","text":"abc"},
     {"key": "property 1", "text": "no"},
     {"key": "property 2", "text": "yes"},
  ]
}

Я определил для них индекс, чтобы ES не выровнял такие объекты, как этот:

PUT /respondereval
{
  "mappings" : {
    "properties": {
      "responses" : {
        "type": "nested"
      }
    }
  }
}

Теперь мне нравится искать первый документ (resp_id 1236) с помощью следующего запроса:

GET /respondereval/_search
{
  "query": {
    "nested": {
      "path": "responses",
      "query": {
        "bool": {
          "must": [
            { "match": { "responses.key": "property 1" } },
            { "match": { "responses.text": "yes" } }
          ]
        }
      }
    }
  }
}

Это должно возвращать только один элемент, который соответствует обоим условиям одновременно.

К сожалению, он всегда возвращает оба документа. Я предполагаю, что это потому, что в какой-то момент ES все еще сглаживает значения в массивах вложенных объектов до чего-то вроде этого (упрощенного):

resp_id 1236: "key":["gender", "property 1", "property 2"], "text:["abc", "yes", "yes"]
resp_id 1237: "key":["gender", "property 1", "property 2"], "text:["abc", "no", "yes"]

, которые оба содержат property1 и yes.

Как правильно решить эту проблему, чтобы возвращались только те документы, которые содержат элемент в массиве объектов, который соответствует обоим условиям ("key": "property 1" AND "text": "yes") одновременно?

Ответы [ 2 ]

2 голосов
/ 03 августа 2020

Проблема с вашим отображением. У вас есть отображение текста, которое по умолчанию использует стандартный анализатор.

Стандартный анализатор создает токены на пробелах. Таким образом,

property 1 будет токенизироваться как

{
    "tokens": [
        {
            "token": "property",
            "start_offset": 0,
            "end_offset": 8,
            "type": "<ALPHANUM>",
            "position": 0
        },
        {
            "token": "1",
            "start_offset": 9,
            "end_offset": 10,
            "type": "<NUM>",
            "position": 1
        }
    ]
}

Аналогично property 2 также.

Следовательно, возвращаются оба документа.

И когда вы ищете yes, он соответствует второму тексту во втором документе. property 1 соответствует property проанализированному токену второго ключа в документе.

Чтобы он работал: - используйте keyword вариацию

{
  "query": {
    "nested": {
      "path": "responses",
      "query": {
        "bool": {
          "must": [
            { "match": { "responses.key.keyword": "property 1" } },
            { "match": { "responses.text.keyword": "yes" } }
          ]
        }
      }
    }
  }
}

Было бы правильно:

{
  "query": {
    "nested": {
      "path": "responses",
      "query": {
        "bool": {
          "must": [
            { "match_phrase": { "responses.key": "property 1" } },//phrase queries
            { "match": { "responses.text": "yes" } }
          ]
        }
      }
    }
  }
}
0 голосов
/ 03 августа 2020

Вы пробовали напрямую запрос must без nested.path

{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "responses.key": "property 1"
          }
        },
        {
          "match": {
            "responses.text": "yes"
          }
        }
      ]
    }
  }
}
...