Я ищу запрос, который вернет значение, отсутствующее в документах из заданного списка значений. Например, в документах есть поле страны со значениями США, Дубай, Сингапур, Япония. Теперь я хочу сказать эластичному поиску, что я даю вам список стран (США, Дубай, Россия), вы даете мне вывод, который говорит, что Россия не является частью какого-либо документа. Это возможно?
Получение пропущенного значения в Elasticsearch
Ответы (1)
Вам нужно выполнить запрос, подобный приведенному ниже, который будет выбирать только документы с США, Дубаем и Россией, а затем агрегировать значения country
.
{
"size": 0,
"query": {
"terms": {
"country": [
"USA",
"Dubai",
"Russia"
]
}
},
"aggs": {
"countries": {
"terms": {
"field": "country"
}
}
}
}
В результате вы получите сегменты для всех присутствующих стран (например, США и Дубай) и не получите сегменты для России.
Затем вы можете выполнить простую арифметику набора, вычитая входной массив с тем, который вы получили из результатов агрегации, и вы найдете то, что вам нужно, то есть:
[USA, Dubai, Russia] - [USA, Dubai] = [Russia]
ОБНОВЛЕНИЕ. Если вы хотите сделать все вышеперечисленное в одной стране, вы можете использовать scripted_metric
агрегация.
map_script
будет выполняться для каждого документа в сегменте и сохранять все существующие страны во временной переменной state.countries
.
reduce_script
собирается работать на координирующем узле и получает результаты всех осколков. Этот скрипт просто сравнивает, какие страны в массиве params.countries
присутствуют, и выводит только страны, которых нет.
POST country/_search
{
"size": 0,
"query": {
"terms": {
"country": [
"USA",
"Dubai",
"Russia"
]
}
},
"aggs": {
"missing_countries": {
"scripted_metric": {
"init_script": "state.countries = [:]",
"map_script": """
def country = doc['country.keyword'].value;
if (!state.countries.containsKey(country)) {
state.countries[country] = 0;
}
state.countries[country]++;
""",
"combine_script": """
return state.countries;
""",
"reduce_script": """
// gather all present countries
def countries = new HashSet();
for (state in states) {
countries.addAll(state.keySet());
}
// figure out which country in params is not present in countries
def missing = [];
for (country in params.countries) {
if (!countries.contains(country)) {
missing.add(country);
}
}
return missing;
""",
"params": {
"countries": ["USA", "Dubai", "Russia"]
}
}
}
}
}
В этом случае выход будет
"aggregations" : {
"missing_countries" : {
"value" : [
"Russia"
]
}
}
"""
на "
и встроить скрипты в одну строку между двойными кавычками. Только Кибана понимает тройные кавычки """
- person Val; 10.11.2020