У меня есть элемент в моем индексе, который содержит поле, представляющее собой массив. Этот массив содержит элементы с полями даты «от» и «до». «От» всегда установлено, но «до» может быть пустым. С моим запросом я, кажется, не могу найти этот конкретный элемент.
{
id: 1234,
items: [
{
from: 1993-01-01,
to: 2007-11-12
},
{
from: 2007-11-13,
},
]
}
Это мой запрос:
{
"bool": {
"must": [
{
"bool": {
"should": [
{
"range": {
"to": {
"gte": 2019
}
}
},
{
"bool": {
"must_not": [
{
"exists": {
"field": "to"
}
}
]
}
}
]
}
},
{
"range": {
"from": {
"lte": "2023-12-31T23:59:59.999"
}
}
}
],
}
}
Я надеялся, что мой товар сверху появится в результатах поиска.
Казалось бы, предложения ИЛИ/СЛЕДУЕТ оцениваются как ложные — каждое из
их для другого элемента в массиве.
Например. :
{
"range": {
"to": {
"gte": 2019
}
}
}
оценивается как false для первого элемента и неприменим для второго.
{
"bool": {
"must_not": [
{
"exists": {
"field": "to"
}
}
]
}
}
оценивается как false для первого элемента.
Итак, false ИЛИ false => false — элемент не найден.
Если этот тезис верен, как сообщить ES, что если один из элементов массива соответствует одному из условий, элемент должен быть в результирующем наборе.
Вам нужно использовать тип вложенного поля и вложенный запрос для поля элементов.
Вложенный тип — это специализированная версия объектного типа данных, позволяет индексировать массивы объектов таким образом, чтобы их можно было запрашиваются независимо друг от друга.
Вот похожий вопрос stackoverflow.
Без использования вложенного поля — , как предложил Мусаб Доган — которое увеличит количество документов в вашем индексе и, следовательно, может повлиять на производительность, я вижу другую возможность исправить, но вам нужно изменить сопоставление индекса и индексация ваших документов.
Это введение null_value
вместо items.to
. Но вам придется явно определить эти (в настоящее время просто отсутствующие) свойства ваших документов с помощью null
.
Чтобы объяснить, почему ваш запрос не работает: массивы, соответственно, значения в массиве по умолчанию выравниваются. (См.: https://www.elastic.co/guide/en/elasticsearch/reference/current/array.html) и не существующие поля/значения пропускаются:
Массив может содержать нулевые значения, которые либо заменяются сконфигурированным значением null_value, либо полностью пропускаются. Пустой массив [] рассматривается как отсутствующее поле — поле без значений.
Таким образом, документ, который вы запрашиваете, выглядит так:
{
id: 1234,
items.from: [ 1993-01-01, 2007-11-13 ],
items.to: [ 2007-11-12 ]
}
Но если вы определяете поле items.to
с применимым и разумным null_value
в вашем случае использования (при условии, что нет items.to
означает что-то вроде «еще не известно, но в будущем», это, вероятно, может быть «2999-12-31»), измените сопоставление соответственно и проиндексируйте items.to
с явным null
, если он не указан, ваш запрос будет работать, как ожидалось.
Итак, если вы измените отображение на:
{
....
"mappings": {
"_doc": {
"properties": {
....
"items": {
"properties": {
....
"to": {
"type": "date",
"null_value": "2999-12-31"
}
}
}
}
}
}
}
и индексировать документы с явным null
как items.to
:
{
"id": 1234,
"items": [
{
"from": "1993-01-01",
"to": "2007-11-12"
},
{
"from": "2007-11-13",
"to": null
}
]
}
ваш запрос будет работать, как и ожидалось, потому что сглаженный документ, который вы запрашиваете, выглядел так:
{
id: 1234,
items.from: [ 1993-01-01, 2007-11-13 ],
items.to: [ 2007-11-12, 2999-12-31 ]
}
Редактировать: Есть НО...
Предполагая, что вы ищете один элемент в массиве items
, который удовлетворяет условиям (это один элемент имеет from
и to
в определенном временном диапазоне), этот способ не точен, потому что совпадения относятся к любой из дат в каждый из сглаженных массивов.
Таким образом, вы также найдете документ, в котором есть первый элемент с from
и to
перед диапазоном, который вы ищете, и еще один элемент с from
и to
после диапазона, который вы ищете.
Чтобы предотвратить это, использование вложенного массива — как сказал @musab-dogan — единственный способ добиться желаемого.
Элементы поля являются вложенными?