ElasticSearch: Как сгруппировать уникальные записи статистики с пересекающимися полями (аккаунт и fingerprint)?

Собственно есть индекс с полями:

  • account_id
  • fingerprint
  • и т.д.

У каждой записи может как быть account_id так и не быть, то-же самое и с fingerprint. Необходимо сгруппировать их по account_id попутно добавив к этим аккаунтам - записи с фингерпринтом которые присутствуют у записей с определённого account_id.

Суть задачи - вывод списка уникальных записей статистики по известным аккаунтам (те у кого имеются account_id + те у кого его нет, но есть такой - же fingerprint как у какой-то из записей в данной группе) и по неизвестным (те у кого только fingerprint) с пагинацией.

Пробовал так:

            'aggs' => [
                "items" => [
                    "composite" => [
                        "sources" => [ 
                            [
                                'account_id' => [
                                    'terms' => [ 'field' => 'account_id' ],
                                ],
                            ], [
                                'fingerprint' => [
                                    'terms' => [ 'field' => 'fingerprint' ],
                                ],
                            ]
                        ],
                    ],
                    "aggs" => [
                        "hits" => [
                            "top_hits" => [
                                "size" => 100
                            ]
                        ]
                    ]

                ],
                
            ]

И как-то так (здесь знаю что код не совсем верный, просто нашёл его в истории):

           'collapse' => [
                'field' => 'account_id',
                'inner_hits' => [ [
                    'name' => 'accounts',
                    'size' => 1,
                    'sort' => [ [ 'timestamp' => 'desc' ] ]
                ],
                [
                    'name' => 'fingerprints',
                    'size' => 1,
                    'sort' => [ [ 'timestamp' => 'desc' ] ]
                ] ],
                "max_concurrent_group_searches" => 4 
            ],

И ещё много как, но что-то всё не то.


Ответы (1 шт):

Автор решения: etki

По-хорошему эти данные нужно процессить вне ES, но можно действительно попробовать коллапснуть

collapse:
  field: fingerprint_id
sort:
  - account_id:
      missing: last

В этом случае выведутся все фингерпринты с соответствующими account_id, если таковой существует для хотя бы одного из идентичных фингерпринтов.

Не уверен, что ситуация, в которой фингерпринты будут корректно сгруппированы под корректным аккаунтом, вообще возможна (потому что первичная группировка однозначно будет по самим фингерпринтам).

→ Ссылка