Поиск документа с пустым полем массива в ElasticSearch

У меня есть набор документов (типа "статья"), и я хочу найти документ, содержащий элементы / объекты, в поле массива

{
    "_type": "article",
    "_source": {
        "title": "Article 1",
        "locations": [
            {
                "address": "ES headquarter",
                "city": "Berlin"
            }
        ]
    }
}

Я хочу два запроса (только один, но с небольшим изменением):

  • получить все статьи, которые имеют места
  • получить все статьи, которые не имеют мест

Я пробовал разные вещи, но, вероятно, я слишком плох с ElasticSearch:

{
  "query": {
    "filtered": {
      "query": {
        "match_all": {}
      },
      "filter": [
        {
          "type": {
            "value": "article"
          }
        },
        {
          "bool": {
            "must_not": {
              "missing": {
                "field": "location",
                "existence": true,
                "null_value": true
              }
            }
          }
        }
      ]
    }
  }
}

это не работает

  • Как бы вы исправить мой запрос?

но в основном:

  • Как бы вы выполнили этот поиск документов с полем, которое является пустым массивом?

4 ответа

Решение

Если address это обязательное поле в location массив вы можете изменить свой запрос:

"must_not": {
  "missing": {
    "field": "locations.address"
  }
}

AFAIK, в ES вы не можете запрашивать неконечные элементы (например, ваши location поле) (см. вопрос), а в случае object типы ES выравнивают вложенные поля (см. вложенный тип, тип объекта). Вот почему я предложил вместо этого запросить один из листовых элементов. Но это требует, чтобы один из них был обязательным (что, к сожалению, не выполняется в вашем случае).

Во всяком случае, я нашел решение, используя _source параметр внутри source_filtering:

"must_not": {
  "script": {
    "script": "_source.locations.size() > 0"
  }
}

Обратите внимание, что с помощью "lang":"groovy" Вы должны написать: "script": "_source.locations.size > 0"

Если вы не хотите включать сценарии, вы можете объединить запрос Exists с запросом must_not bool, например:

{
  "query":{
    "bool":{
      "must_not":[
        {
          "exists":{
            "field":"tags"
          }
        }
      ]
    }
  }
}

Согласно документации Elasticsearch

Пустой массив рассматривается как отсутствующее поле — поле без значений.

Предположим, у вас есть два документа вarticle-indexиндекс

      # First document
{
    "_type": "article",
    "_source": {
        "title": "Article 1",
        "locations": [{"address": "ES headquarter", "city": "Berlin"}]
    }
}
# Second document
{
    "_type": "article",
    "_source": {
        "title": "Article 2",
        "locations": []
    }
}

Ожидаемые запросы:

  1. Получить все статьи, которые имеют местоположения
      GET article-index/_search
{
  "query": {
    "exists": {
       "field": "locations"
    }
  }
}
  1. получить все статьи, у которых НЕТ местоположений
      GET article-index/_search
{
  "query": { 
    "bool": {
      "must": {
        "exists": {
          "field": "locations"
        }
      }
    }
  }
}

Похоже, что на аналогичный вопрос был получен ответ, я не тестировал решение, но вы могли бы попробовать его: >> Эластичная фильтрация по размеру поля, являющегося массивом.

Другие вопросы по тегам