Подтвердить что ты не робот

Элементы фильтра, в котором массив содержит любое из заданных значений

У меня есть набор документов вроде

{
    tags:['a','b','c']
    // ... a bunch properties
}

Как указано в заголовке: есть ли способ фильтровать все документы, содержащие какие-либо из указанных тегов, используя Nest?

Например, вышеприведенная запись будет соответствовать ['c', 'd']

Или мне нужно создать несколько "OR" вручную?

4b9b3361

Ответ 1

Изменить: ниже приведенный ниже набор битов, возможно, интересный, но сам ответ немного устарел. Некоторые из этих функций меняются в 2.x. Кроме того, Slawek указывает в другом ответе, что запрос terms - это простой способ DRY выполнить поиск в этом случае. Реализован в конце для современных передовых методов. -NZ

Вероятно, вам понадобится Bool Query (или, скорее всего, Filter рядом с другим запросом), с предложением should.

Запрос bool имеет три основных свойства: must, should и must_not. Каждый из них принимает другой запрос или массив запросов. Названия предложений довольно понятны; в вашем случае предложение should может указывать фильтры списка, совпадение с любым из которых возвращает документ, который вы ищете.

Из документов:

В булевом запросе без предложений must одно или несколько предложений should должны совпадать с документом. Минимальное количество совпадающих статей должно быть задано с помощью параметра minimum_should_match.

Вот пример того, что этот запрос Bool может выглядеть как отдельный:

{
  "bool": {
    "should": [
      { "term": { "tag": "c" }},
      { "term": { "tag": "d" }}
    ]
  }
}

И вот еще один пример этого запроса Bool как фильтра в более общем Отфильтрованном запросе:

{
  "filtered": {
    "query": {
      "match": { "title": "hello world" }
    },
    "filter": {
      "bool": {
        "should": [
          { "term": { "tag": "c" }},
          { "term": { "tag": "d" }}
        ]
      }
    }
  }
}

Используете ли вы Bool в качестве запроса (например, чтобы влиять на количество совпадений) или как фильтр (например, для уменьшения ударов, которые затем оцениваются или постфильтруются) являются субъективными, в зависимости от ваших требований.

Обычно предпочтительнее использовать Bool в пользу или фильтра, если у вас нет причин использовать And/Or/Not (такие причины существуют). В блоге Elasticsearch есть больше информации о различных реализациях каждого из них, а также о хороших примерах того, когда вы можете предпочесть Bool над And/Or/Not и наоборот.

Elasticsearch blog: Все о билетах фильтра Elasticsearch

Обновить с помощью рефакторированного запроса...

Теперь, со всем этим, запрос terms является версией DRYer всего вышеперечисленного. Он делает правильные действия в отношении типа запроса под капотом, он ведет себя так же, как bool + should, используя параметры minimum_should_match, и в целом немного более кратким.

Здесь этот последний запрос немного реконструировал:

{
  "filtered": {
    "query": {
      "match": { "title": "hello world" }
    },
    "filter": {
      "terms": {
        "tag": [ "c", "d" ],
        "minimum_should_match": 1
      }
    }
  }
}

Ответ 2

Здесь также запрос терминов, который должен сэкономить вам некоторую работу. Вот пример из документов:

{
  "terms" : {
      "tags" : [ "blue", "pill" ],
      "minimum_should_match" : 1
  }
}

Под капотом он строит логическое значение. Так что это в основном то же самое, что и выше, но короче.

Также существует соответствующий фильтр терминов.

Итак, чтобы суммировать ваш запрос, может выглядеть так:

{
  "filtered": {
    "query": {
      "match": { "title": "hello world" }
    },
    "filter": {
      "terms": {
        "tags": ["c", "d"]
      }
    }
  }
}

С большим количеством тегов это может существенно повлиять на длину.

Ответ 3

Хотя это старый вопрос, я недавно столкнулся с этой проблемой, и некоторые ответы здесь устарели (как отмечают комментарии). Таким образом, для блага других, кто мог здесь случайно наткнуться:

Запрос term можно использовать для нахождения точного термина, указанного в обратном индексе:

{
  "query": {
   "term" : { "tags" : "a" }
} 

Из документации https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-term-query.html

В качестве альтернативы вы можете использовать запрос terms, который будет сопоставлять все документы с любым из элементов, указанных в данном массиве:

{
  "query": {
   "terms" : { "tags" : ["a", "c"]}
} 

https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-terms-query.html

Нужно знать (что меня поймало) - то, как вы определяете документ, также имеет значение. Если искомое поле было проиндексировано как тип text, то Elasticsearch выполнит полнотекстовый поиск (т.е. используя строку analyzed).

Если вы проиндексировали поле как keyword, то выполняется поиск по ключевому слову с использованием "неанализированной" строки. Это может оказать огромное практическое влияние, так как анализируемые строки предварительно обрабатываются (в нижнем регистре, пунктуации и т.д.). См. (https://www.elastic.co/guide/en/elasticsearch/guide/master/term-vs-full-text.html)

Чтобы избежать этих проблем, строковое поле разделено на два новых типа: текст, который следует использовать для полнотекстового поиска, и ключевое слово, которое следует использовать для поиска по ключевым словам. (https://www.elastic.co/blog/strings-are-dead-long-live-strings)