#elasticsearch
#elasticsearch
Вопрос:
У меня есть следующие данные:
[{
"id": "1",
"listItems": [
{
"key": "li1",
"value": 100
},
{
"key": "li2",
"value": 5000
}
]
},
{
"id": "2",
"listItems": [
{
"key": "li3",
"value": 200
},
{
"key": "li2",
"value": 2000
}
]
}]
Я пытаюсь выполнить фильтр NumericRangeQuery, чтобы минимальное значение в списках каждого документа совпадало с диапазоном. Так, например, мой диапазон составляет от 150 до 15000.
Единственный способ, которым я знаю, как это написать, — это использовать запрос скрипта, но, похоже, он не работает, поскольку код по-прежнему, похоже, захватывает любое значение в ListItems, чтобы попытаться сопоставить с диапазоном, вместо того, чтобы захватывать минимальное значение, как я сказал. Вот мой запрос:
{
"track_total_hits": true,
"from": 0,
"min_score": 0.0,
"query": {
"bool": {
"must": [
{
"nested": {
"path": "listItems",
"query": {
"script": {
"script": "double minVal = 0; minVal = doc['listItems.value'][0]; for (wp in doc['listItems.value']) {if (wp < minVal) { minVal = wp;}} return minVal >= 150 amp;amp; minVal <= 15000"
}
}
}
}
]
}
}}
Кто-нибудь видит что-то, чего я не вижу?
Комментарии:
1. у вас была возможность просмотреть мой ответ, с нетерпением жду обратной связи от вас 🙂
2. привет, спасибо, что ответили еще раз, пожалуйста, смотрите Мой вопрос ниже.
Ответ №1:
Поисковый запрос выполняет следующую агрегацию :
- Агрегирование терминов по
id
полю - Минимальная агрегация на
listItems.value
- Агрегирование выбора корзины, представляющее собой агрегацию родительского конвейера, которая выполняет сценарий, определяющий, будет ли сохранен текущий сегмент в родительской агрегации с несколькими сегментами.
Добавление рабочего примера с отображением индекса, индексными данными, поисковым запросом и результатом поиска
Сопоставление индексов:
{
"mappings": {
"properties": {
"listItems": {
"type": "nested"
},
"id":{
"type":"text",
"fielddata":"true"
}
}
}
}
Индексировать данные:
{
"id" : "1",
"listItems" :
[
{
"key" : "li1",
"value" : 100
},
{
"key" : "li2",
"value" : 5000
}
]
}
{
"id" : "2",
"listItems" :
[
{
"key" : "li3",
"value" : 200
},
{
"key" : "li2",
"value" : 2000
}
]
}
Поисковый запрос:
{
"size": 0,
"aggs": {
"id_terms": {
"terms": {
"field": "id"
},
"aggs": {
"nested_entries": {
"nested": {
"path": "listItems"
},
"aggs": {
"min_position": {
"min": {
"field": "listItems.value"
}
}
}
},
"value_range": {
"bucket_selector": {
"buckets_path": {
"totalValues": "nested_entries>min_position"
},
"script": "params.totalValues >= 150 amp;amp; params.totalValues < 15000"
}
}
}
}
}
}
Результат поиска:
"aggregations": {
"id_terms": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "2",
"doc_count": 1,
"nested_entries": {
"doc_count": 2,
"min_position": {
"value": 200.0
}
}
}
]
}
}
Комментарии:
1. Привет, спасибо за ответ еще раз. Итак, единственный способ сделать это — с помощью агрегирования, а не с помощью обычного поискового запроса или фильтра документа? Похоже, это работает, но это усложняет мой существующий код, потому что мой документ намного больше, чем этот, с гораздо большей фильтрацией, чем просто попытка найти максимальное минимальное значение. У нас есть отдельная логика для агрегирования содержимого и фактического поиска и возврата содержимого документа для отображения (если это имеет смысл).
2. @user989953 Спасибо за ваш ответ 🙂 Я не думаю, что это возможно с использованием обычного поискового запроса или фильтра, так как вы хотите найти минимальное значение из каждого сегмента (которое должно быть создано с помощью агрегации). И затем к сформированным сегментам вы хотите применить диапазон. Таким образом, в соответствии с вашим вариантом использования и требованиями, мы можем получить требуемый результат, используя только агрегации.
3. Я пошел дальше и пометил ваш ответ как ответ, поскольку смог применить его к своему коду с парой незначительных настроек, чтобы заставить его работать так, как мне нужно. Еще раз спасибо за помощь.