Как запросить ElasticSearch, чтобы найти объекты по крайней мере с одним термином не в массиве - PullRequest
0 голосов
/ 07 февраля 2019

В этой задаче, скажем, у нас есть отображение типа

{
  tags: { type: 'string' }, // array of strings input
  name: { type: 'string' }
}

, где тегам дается массив.Скажем, мы затем индексируем следующие документы:

[{
  tags: ['a', 'b', 'c'],
  name: 'Alpha'
}, {
  tags: ['b', 'c', 'd'],
  name: 'Beta'
}, {
  tags: ['c', 'd', 'e'],
  name: 'Gamma'
}, {
  tags: ['b', 'c', 'd', 'e'],
  name: 'Delta'
}, {
  tags: [],
  name: 'Eta'
}]

Есть ли способ структурировать запрос так, чтобы он мог найти все документы, имеющие хотя бы один тег , а не в данном массиве?Например, учитывая ['b', 'c', 'd'] , он должен возвращать объекты с именем Alpha (у которых 'a' отсутствует в данном массиве), Gamma (у которого 'e' отсутствует в данном массиве) и Delta (у которого также 'e' нет в данном массиве).

Ответы [ 2 ]

0 голосов
/ 11 февраля 2019

Боюсь, что это невозможно, поскольку Elasticsearch хранит данные в инвертированных индексах , структуре данных, которая может ответить на вопрос «какие документы имеют определенный токен», а не «какие документы не имеют»есть другие токены ".

Есть несколько вещей, которые вы можете попробовать.

Укажите соответствие tags явно

Это можно сделать, если набор всех возможных tags известно заранее, и количество элементов в поле (== число уникальных тегов) не слишком велико (скажем, меньше 1000).

Если набор возможных значений неизвестен, онможно получить с помощью агрегации terms.В этом случае вам придется выполнить 2 запроса вместо 1.

В примере из вашего вопроса это будет означать запрос всех документов с тегами в ["a", "e"].

Использование script query

script запрос по сути является запросом full-scan и позволяет пользователю определять критерии совпадения / несоответствия по своему усмотрению.Основным недостатком является производительность, поскольку Elasticsearch не сможет использовать ни один из своих инвертированных индексов, ему, по сути, придется сканировать все документы.

Этот параметр может оказаться полезным в некоторых обстоятельствах, например, для выполненияпроанализировать или доказать некоторую гипотезу.

Изменить данные

Поскольку универсальный подход неосуществим, может оказаться, что ваше экономическое обоснование на самом деле не является универсальным.Посмотрите на запросы, которые вам нужно выполнить, и оптимизируйте их под ваши сценарии использования.

Например, если вы ищете "любые теги , но b, c, d"- это повторяющийся вариант использования, определите флагоподобное поле "contains_not_b_c_d" и предварительно рассчитайте его.

Мне бы очень хотелось придумать что-то более позитивное в этом ответе, но этот вариант использованияне там, где процветает Elasticsearch.


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

0 голосов
/ 08 февраля 2019

Если вы можете изменить концепцию «входного массива» как логический запрос - это будет работать

 {
  "query": {
    "bool": {
      "should": [
        {
          "bool": {
            "must_not": {
              "term": {
                "tags": "b"
              }
            }
          }
        },
        {
          "bool": {
            "must_not": {
              "term": {
                "tags": "c"
              }
            }
          }
        },
        {
          "bool": {
            "must_not": {
              "term": {
                "tags": "d"
              }
            }
          }
        }
      ],
      "must" : { "wildcard" : {"tags": "*"}},
      "minimum_should_match": 1
    }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...