#elasticsearch #elasticsearch-aggregation #elasticsearch-dsl
#elasticsearch #elasticsearch-агрегирование #elasticsearch-dsl
Вопрос:
Я пытался применить агрегатную функцию, например: сумма по типу текста, мои индексные сопоставления приведены ниже :
{
"my_elastic_search_index" : {
"mappings" : {
"properties" : {
"@timestamp" : {
"type" : "date"
},
"@version" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"doc" : {
"properties" : {
"_id" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"last_updated_on" : {
"type" : "long"
},
"sample_ids" : {
"type" : "nested",
"properties" : {
"name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"value" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
},
"status" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"filter_id" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
},
"query" : {
"properties" : {
"match" : {
"properties" : {
"doc" : {
"properties" : {
"filter_id" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
}
}
}
}
}
}
Мои данные :
{
"took" : 23,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 4,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "my_elastic_search_index",
"_type" : "_doc",
"_id" : "zzz-yyy-xxx-a9e8",
"_score" : 1.0,
"_source" : {
"@version" : "1",
"@timestamp" : "2019-11-14T14:30:56.261Z",
"doc" : {
"status" : "SENT",
"sample_ids" : [
{
"value" : """"20"""",
"name" : "8f4abde123d"
},
{
"value" : """"25.52"""",
"name" : "d92c4732bc9fb91"
},
{
"value" : """"0"""",
"name" : "4b91bdee68b6e"
},
{
"value" : """"xyz"""",
"name" : "bd0a944a292d5a"
},
{
"value" : """"someothervlue"""",
"name" : "8ee9932060d5bf"
},
{
"value" : """"30..01"""",
"name" : "229eed093fa0d85"
},
],
"filter_id" : "a1357913-cf99650f51d",
"_id" : "zzz-yyy-xxx-a9e81",
}
}
},
{
"_index" : "my_elastic_search_index",
"_type" : "_doc",
"_id" : "zzz-yyy-xxx-a9e82",
"_score" : 1.0,
"_source" : {
"@version" : "1",
"@timestamp" : "2019-11-14T14:30:56.731Z",
"doc" : {
"status" : "SENT",
"sample_ids" : [
{
"value" : """"40"""",
"name" : "8f4abde123d"
},
{
"value" : """"0"""",
"name" : "d92c47372bc9fb91"
},
{
"value" : """"0"""",
"name" : "4b91bdc6ee68b6e"
},
{
"value" : """"0"""",
"name" : "bccf07c19cfe12c"
}
],
"filter_id" : "a1357913-cf99650f51d",
"_id" : "zzz-yyy-xxx-a9e84",
},
}
},
{
"_index" : "my_elastic_search_index",
"_type" : "_doc",
"_id" : "zzz-yyy-xxx-a9e85",
"_score" : 1.0,
"_source" : {
"@version" : "1",
"@timestamp" : "2019-11-14T08:23:36.998Z",
"doc" : {
"status" : "SENT",
"sample_ids" : [
{
"value" : """"17.8"""",
"name" : "8f4abde123d"
},
{
"value" : """"35.6"""",
"name" : "d92c473132bc9fb91"
},
{
"value" : """"0"""",
"name" : "4b91bd5c6ee68b6e"
},
{
"value" : """"35.6"""",
"name" : "bd0a944c2a292d5a"
},
{
"value" : """"0"""",
"name" : "8ee9934dce9e2060d5bf"
},
{
"value" : """"0"""",
"name" : "229eed48xsscd3fa0d85"
},
{
"value" : """"30"""",
"name" : "4381f1bddffc4265129"
},
{
"value" : """"0"""",
"name" : "94cafdd1c78fc355b00"
},
{
"value" : """"HVDC"""",
"name" : "bccf024ac19cfe12c"
}
],
"filter_id" : "a1357913-cf99650f51d",
"_id" : "zzz-yyy-xxx-a9e84",
}
}
},
{
"_index" : "my_elastic_search_index",
"_type" : "_doc",
"_id" : "zzz-yyy-xxx-a9e87",
"_score" : 1.0,
"_source" : {
"@version" : "1",
"@timestamp" : "2019-11-14T08:24:01.272Z",
"doc" : {
"sample_ids" : [
{
"value" : """"11.08"""",
"name" : "8f4abde123d"
},
{
"value" : """"35.6"""",
"name" : "d92c4737a132bc9fb91"
},
{
"value" : """"0"""",
"name" : "4b91bd5028c6ee68b6e"
},
{
"value" : """"35.6"""",
"name" : "bd0a9445e19c2a292d5a"
},
{
"value" : """"0"""",
"name" : "8ee9934dd002060d5bf"
},
{
"value" : """"0"""",
"name" : "229eed48e2093fa0d85"
}
],
"filter_id" : "a1357913-cf99650f51d",
}
}
}
]
}
}
Я хочу вернуть результат суммы doc.sample_ids.value как 88,88, где doc.sample_ids.name = 8f4abde123d и filter_id = a1357913-cf99650f51d , уже пытался привести doc.sample_ids.name в число, и это выдает мне ошибку.
В любом случае, я могу получить сумму, среднее значение и количество.
GET /my_elastic_search_index/_search
{
"query": {
"bool": {
"must": [
{
"terms": {
"doc.filter_id.keyword": [
"a1357913-cf99650f51d"
]
}
}
]
}
},
"aggs": {
"sum_values" : { "sum" : { "script" : {
"lang":"painless", "inline" : "Double.parseDouble(doc['sample_ids.value'])" } } } }
}
Комментарии:
1. 1. «sample_ids.value» Всегда ли это содержит число? Если да, то почему поле хранится в виде текста? 2. Почему «»»»35.6″»»»», а не «35.6»?
2. @SahilGupta sample_ids может содержать текст в некоторых строках, и я не уверен, почему это «»»»35.6″»»»», а не «35.6»
Ответ №1:
Вы используете вложенное поле, поэтому вам придется использовать вложенную агрегацию:
Попробуйте с такой агрегацией:
{
"aggs": {
"resellers": {
"nested": {
"path": "doc.sample_ids"
},
"aggs": {
"sum_values": {
"sum": {
"script": {
"lang": "painless",
"source": "Float.parseFloat(doc['doc.sample_ids.value.keyword'].value)"
}
}
}
}
}
}
}
С такими данными, как это : «»»»35.6″»»»
Сначала вы должны очистить свои данные.
Это недопустимый формат, он не должен храниться таким образом.
Вы можете сделать это путем переиндексации данных или с помощью loigstash или с помощью обновления по запросу.
Но если вы действительно не можете это исправить, вам придется включить возможности регулярных выражений в вашем elasticsearch.yml.
Добавьте эту строку :
script.painless.regex.enabled: true
Тогда вы сможете сделать что-то вроде этого:
"aggs": {
"sum_values": {
"sum": {
"script": {
"lang": "painless",
"source": """
String content = /["]/.matcher(doc['doc.sample_ids.value.keyword'].value).replaceAll('');
Double.parseDouble(content);
"""
}
}
}
}
Будьте осторожны с этим запросом, производительность будет ужасной.
Вам действительно следует решить проблему с проглатыванием и очистить ваши данные.
Комментарии:
1. Какое еще преобразование мне нужно, на самом деле это «»»»35.6″»»»»
2. Это выдает мне ошибку: « «скрипт»: «Float.parseFloat(doc[‘doc.sample_ids.value. ключевое слово’].значение)», «lang»: «безболезненный», «caused_by»: { «тип»: «исключение number_format_exception», «причина»: «Для входной строки: «»0″»» } «
3. есть ли у нас какой-либо альтернативный способ? и повлияет ли производительность только на этот запрос или на другие тоже?
4. единственный рекомендуемый способ сделать это для меня — очистить ваши данные. Вы можете создать идентификатор с помощью своего api или с помощью конвейера на стороне elastic и обновлять по запросу, но если ваши данные не являются чистыми, это будет стоить во время запроса. Если запрос тяжелый, это может потенциально повлиять на другой запрос в вашем кластере. Более того, если у вас есть только один узел.