Elasticsearch: агрегирование метрик по сценарию возвращает странную группировку

Я получаю неожиданный результат, и я немного потерян.

Я добавил эти документы:

POST es_test/_doc/_bulk?pretty
{ "index": {}}
{ "firstname": "John", "lastname": "Doe", "age": 22, "birthdate": "1980-01-20T12:30:00Z" }
{ "index": {}}
{ "firstname": "May", "lastname": "Greenwood", "age": 19, "birthdate": "1980-01-20T12:30:00Z" }
{ "index": {}}
{ "firstname": "Marry", "lastname": "Hilake", "age": 32, "birthdate": "1970-01-20T12:30:00Z" }
{ "index": {}}
{ "firstname": "Mister", "lastname": "X", "age": 20, "birthdate": "1990-11-23T12:30:00Z" }

Это все хорошо, когда я запрашиваю их так:

GET es_test/_doc/_search

Проблема возникает, когда я добавляю безболезненный скрипт:

GET es_test/_doc/_search    
{
  "size": 0,
  "aggs": {
    "user": {
      "scripted_metric": {
        "init_script" : "params._agg.transactions = []",
        "map_script" : "params._agg.transactions.add(params._source)"
      }
    }
  }
}

Вывод выглядит следующим образом:

{
  "took": 0,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 4,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "user": {
      "value": [
        {
          "transactions": [
            {
              "firstname": "John",
              "birthdate": "1980-01-20T12:30:00Z",
              "age": 22,
              "lastname": "Doe"
            },
            {
              "firstname": "John",
              "birthdate": "1980-01-20T12:30:00Z",
              "age": 22,
              "lastname": "Doe"
            }
          ]
        },
        {
          "transactions": []
        },
        {
          "transactions": [
            {
              "firstname": "May",
              "birthdate": "1980-01-20T12:30:00Z",
              "age": 19,
              "lastname": "Greenwood"
            }
          ]
        },
        {
          "transactions": []
        },
        {
          "transactions": [
            {
              "firstname": "Marry",
              "birthdate": "1970-01-20T12:30:00Z",
              "age": 32,
              "lastname": "Hilake"
            }
          ]
        }
      ]
    }
  }
}

Первый массив transactions включает в себя два раза Джона, второй пуст, затем идет май, снова пустой и, наконец, Жениться. Понятия не имею, почему он так странно сгруппирован.

Желаемый результат — один массив, включающий всех пользователей (Джон, Мэй, Марри, Мистер).

Я ценю вашу помощь, спасибо! Игра


person scth    schedule 13.06.2018    source источник


Ответы (1)


Для этого вам придется использовать reduce_script. Это работает

GET es_test/_doc/_search
{
  "size": 0,
  "aggs": {
    "user": {
      "scripted_metric": {
        "init_script": "params._agg.transactions = []",
        "map_script": "params._agg.transactions.add(params._source)",
        "reduce_script": """
                ArrayList transactions = []; 
                for (a in params._aggs) { 
                  transactions.addAll(a.transactions) 
                } 
                return transactions
"""
      }
    }
  }
}

Результат

{
  "took": 12,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 4,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "user": {
      "value": [
        {
          "firstname": "John",
          "birthdate": "1980-01-20T12:30:00Z",
          "age": 22,
          "lastname": "Doe"
        },
        {
          "firstname": "Marry",
          "birthdate": "1970-01-20T12:30:00Z",
          "age": 32,
          "lastname": "Hilake"
        },
        {
          "firstname": "Mister",
          "birthdate": "1990-11-23T12:30:00Z",
          "age": 20,
          "lastname": "X"
        },
        {
          "firstname": "Mister",
          "birthdate": "1990-11-23T12:30:00Z",
          "age": 20,
          "lastname": "X"
        }
      ]
    }
  }
}

Обновите, ниже работает, это та же агрегация, но она использует только часть источника, что очень странно.

GET es_test/_search
{
  "size": 0,
  "query": {
    "match_all": {}
  },
  "aggs": {
    "user": {
      "scripted_metric": {
        "params": {
          "_agg": {}
        },
        "init_script": "params._agg.transactions = []",
        "map_script": "params._agg.transactions.add(params._source.firstname + ' ' + params._source.lastname)",
        "reduce_script": """
                ArrayList transactions = []; 
                for (a in params._aggs) { 
                  transactions.addAll(a.transactions) 
                } 
                return transactions
"""
      }
    }
  }
}

Результат

{
  "took": 18,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 4,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "user": {
      "value": [
        "John Doe",
        "May Greenwood",
        "Marry Hilake",
        "Mister X"
      ]
    }
  }
}
person Alkis Kalogeris    schedule 13.06.2018
comment
Благодарю вас! К сожалению, все еще есть ошибка. Как видите, Mister выведен дважды, а May отсутствует. Ты знаешь почему? - person scth; 14.06.2018
comment
Я обновил свой ответ. Я не знаю, почему это происходит, но это очень странно. Если вы используете часть _source, все работает нормально. - person Alkis Kalogeris; 14.06.2018
comment
Также убедитесь, что вы увеличили размер больше, чем по умолчанию. - person MikBTC; 27.02.2021