Как мы можем агрегировать СУММУ по столбцу типа text в эластичном поиске?

#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 и обновлять по запросу, но если ваши данные не являются чистыми, это будет стоить во время запроса. Если запрос тяжелый, это может потенциально повлиять на другой запрос в вашем кластере. Более того, если у вас есть только один узел.