Поиск документа с пустым полем массива в 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": []
}
}
Ожидаемые запросы:
- Получить все статьи, которые имеют местоположения
GET article-index/_search
{
"query": {
"exists": {
"field": "locations"
}
}
}
- получить все статьи, у которых НЕТ местоположений
GET article-index/_search
{
"query": {
"bool": {
"must": {
"exists": {
"field": "locations"
}
}
}
}
}
Похоже, что на аналогичный вопрос был получен ответ, я не тестировал решение, но вы могли бы попробовать его: >> Эластичная фильтрация по размеру поля, являющегося массивом.