Как мне выполнить поиск по одному полю с несколькими значениями в elasticsearch?

#elasticsearch

#elasticsearch

Вопрос:

Я хочу создать поисковый запрос таким образом, чтобы я возвращал paragraph_ids 1 и 2 для document_id 299. Способ построения моего запроса в настоящее время этого не происходит.

Вот некоторые репрезентативные данные:

 {
    "document_id": "299",
    "date": "2014-06-21",
    "paragraph_id": "1",
    "text": "foo"
}

{
    "document_id": "299",
    "date": "2014-12-24",
    "paragraph_id": "2",
    "text": "bar"
}

{
    "document_id": "314",
    "date": "2014-07-01",
    "paragraph_id": "1",
    "text": "I thought what I'd do was, I'd pretend I was one of those deaf-mutes."
}

{
    "document_id": "272",
    "date": "2014-08-01",
    "paragraph_id": "2",
    "text": "I saw the best minds of my generation destroyed by madness starving hysterical..."
}
 

Вот мой запрос:

Запрос 1

 {"query": {
    "bool": {
        "must": [{"range": {"date": {"lte": "2015-01-01","gte": "2014-01-01"}}}],
        "should": [{"match": {"paragraph_id": "1"}}, {"match": {"paragraph_id": "2"}}],
        "filter": [{"bool": {"should": [{"match_phrase": {"document_id": "299"}}]}}]
        }
    }
}
 

Я ожидаю, что мои результаты будут содержать paragraph_ids 1 и 2 для document_id 299. Однако мои результаты содержат document_ids 299, 314 и 272.

Когда я ищу один paragraph_id, я получаю ожидаемый результат. Вот пример запроса:
Запрос 2

 {"query": {
    "bool": {
        "must": [{"range": {"date": {"lte": "2015-01-01","gte": "2014-01-01"}}},
                 {"match": {"paragraph_id": "1"}}],
        "filter": [{"bool": {"should": [{"match_phrase": {"document_id": "299"}}]}}]
        }
    }
}
 

Когда я включаю несколько операторов сопоставления paraphraph_id, я не получаю никаких результатов:

Запрос 3

 {"query": {
    "bool": {
        "must": [{"range": {"date": {"lte": "2015-01-01","gte": "2014-01-01"}}},
                 {"match": {"paragraph_id": "1"}},
                 {"match": {"paragraph_id": "2"}}],
        "filter": [{"bool": {"should": [{"match_phrase": {"document_id": "299"}}]}}]
        }
    }
}
 

Как я могу написать запрос таким образом, чтобы я получал только paragraph_ids 1 и 2 для document_id 299?

Ответ №1:

must совпадает с оператором logical AND и should совпадает с оператором logical OR

В третьем поисковом запросе у вас есть must предложение с тремя условиями, которые включают запрос диапазона и запросы соответствия для paragaraph_id — 1 и 2, но нет ни одного документа, который удовлетворял бы всем трем условиям. Итак, по этому запросу вы получите пустой результат поиска.

 {
  "query": {
    "bool": {
      "must": [                        // note this
        {
          "range": {
            "date": {
              "lte": "2015-01-01",
              "gte": "2014-01-01"
            }
          }
        },
        {
          "match": {
            "paragraph_id": "1"
          }
        },
        {
          "match": {
            "paragraph_id": "2"
          }
        }
      ],
      "filter": [
        {
          "bool": {
            "should": [
              {
                "match_phrase": {
                  "document_id": "299"
                }
              }
            ]
          }
        }
      ]
    }
  }
}
 

Вам нужно использовать should предложение для нескольких paragraph_id , как показано ниже

 {
  "query": {
    "bool": {
      "must": [
        {
          "range": {
            "date": {
              "lte": "2015-01-01",
              "gte": "2014-01-01"
            }
          }
        }
      ],
      "should": [
        {
          "match": {
            "paragraph_id": "1"
          }
        },
        {
          "match": {
            "paragraph_id": "2"
          }
        }
      ],
      "filter": [
        {
          "bool": {
            "should": [
              {
                "match_phrase": {
                  "document_id": "299"
                }
              }
            ]
          }
        }
      ]
    }
  }
}
 

Результатом поиска будет

 "hits": [
      {
        "_index": "66342299",
        "_type": "_doc",
        "_id": "1",
        "_score": 1.6931472,
        "_source": {
          "document_id": "299",
          "date": "2014-06-21",
          "paragraph_id": "1",
          "text": "foo"
        }
      },
      {
        "_index": "66342299",
        "_type": "_doc",
        "_id": "2",
        "_score": 1.6931472,
        "_source": {
          "document_id": "299",
          "date": "2014-12-24",
          "paragraph_id": "2",
          "text": "bar"
        }
      }
    ]
 

Комментарии:

1. Я собираюсь задать еще один вопрос, потому что это не совсем та проблема, с которой я столкнулся. Проблема в том, что document_id 299 действительно содержит 3 абзаца с идентификаторами от 1 до 3. Мне нужны только пункты 1 и 2, а не 3. Когда я запускаю ваш запрос, это похоже на мой запрос № 2, я получаю третий абзац.

2. Ваш ответ отвечает на поставленный вопрос. Я понял, что мне нужен новый вопрос для более конкретного решения проблемы.