ElasticSearch вложенный NumericRangeQuery с использованием минимального значения из списка для сравнения

#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:

Поисковый запрос выполняет следующую агрегацию :

  1. Агрегирование терминов по id полю
  2. Минимальная агрегация на listItems.value
  3. Агрегирование выбора корзины, представляющее собой агрегацию родительского конвейера, которая выполняет сценарий, определяющий, будет ли сохранен текущий сегмент в родительской агрегации с несколькими сегментами.

Добавление рабочего примера с отображением индекса, индексными данными, поисковым запросом и результатом поиска

Сопоставление индексов:

 {
  "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. Я пошел дальше и пометил ваш ответ как ответ, поскольку смог применить его к своему коду с парой незначительных настроек, чтобы заставить его работать так, как мне нужно. Еще раз спасибо за помощь.