Как агрегировать по динамическим или неизвестным полям в Elasticsearch 6.x - PullRequest
0 голосов
/ 23 октября 2019

Я довольно новичок в ElasticSearch, в настоящее время использую v6.2, и мне кажется, что я столкнулся с проблемой при попытке добавить некоторые агрегации в запрос. Попытка обернуть голову вокруг различных типов агрегации, а также лучших способов хранения данных.

Когда запрос выполняется, у меня есть некоторые переменные атрибуты, которые я хотел бы объединить, а затем вернуть в качестве фильтровпользователю. Например, один символ может иметь атрибуты для «размера», «формы» и «цвета», в то время как другой имеет только «форму» и «цвет».

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

Мои данные в настоящее время структурированы следующим образом:

{
    id : 1,
    title : 'New Character 1',
    group : 1,
    region : 1,
    attrs : [
        moves : 2,

        # These would be dynamic, would only apply to some rows, not others.
        var_colours : ['Blue', Green', 'Red'],
        var_shapes : ['Round', 'Square', 'Etc'],

        effects : [
            { id : 1, value: 20},
            { id : 2, value: 60},
            { id : 3, value: 10},
        ]

    ]
}

В настоящее время у меня есть совокупность групп и регионов, которая выглядит следующим образом. Кажется, он работает замечательно, и я хотел бы добавить что-то похожее для атрибутов.

[
    'aggs' => [
        'group_ids' => [
            'terms' => [
                'field' => 'group',
                'order' => [ '_count' => 'desc' ]
            ]
        ],
        'region_ids' => [
            'terms' => [
                'field' => 'region',
                'order' => [ '_count' => 'desc' ]
            ]
        ]
    ]
]

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

[aggregations] => [
    [groups] => [
        [doc_count_error_upper_bound] => 0
        [sum_other_doc_count] => 0
        [buckets] => [
            [0] => [
                [key] => 5
                [doc_count] => 27
            ],
            [1] => [
                [key] => 2
                [doc_count] => 7
            ]
        ]
    ],

    [var_colours] => [
        [doc_count_error_upper_bound] => 0
        [sum_other_doc_count] => 0
        [buckets] => [
            [0] => [
                [key] => 'Red'
                [doc_count] => 27
            ],
            [1] => [
                [key] => 'Blue'
                [doc_count] => 7
            ]
        ]
    ],

    [var_shapes] => [
        [doc_count_error_upper_bound] => 0
        [sum_other_doc_count] => 0
        [buckets] => [
            [0] => [
                [key] => 'Round'
                [doc_count] => 27
            ],
            [1] => [
                [key] => 'Polygon'
                [doc_count] => 7
            ]
        ]
    ]

    // ...
]

Любое понимание, которое кто-либо может предоставить, было бы чрезвычайно полезно.

1 Ответ

0 голосов
/ 24 октября 2019

Вы должны сделать это в своем PHP-скрипте.

Я могу подумать о следующем:

  1. Использовать Динамическое отображение поля для вашего индекса.

По умолчанию, когда в документе найдено ранее невидимое поле, Elasticsearch добавит новое поле в отображение типа. Это поведение можно отключить как в документе, так и на уровне объекта, установив для динамического параметра значение false (игнорировать новые поля) или строгое (вывести исключение при обнаружении неизвестного поля).

Получить все существующие поля в вашем индексе. Для этого используйте Get mapping API .

Зацикливайтесь на результатах шага 2, чтобы вы могли получить все существующие поля в вашем индексе. Вы можете хранить их в списке (или массиве), например.

Вы можете создать PHP Elasticsearch агрегирование терминов для каждого из полей в вашем списке (или массив). Это: создайте пустой или базовый запрос без агрегирования терминов и добавьте по одному термину для каждого элемента, полученного на шаге 3.

Добавьте к каждому термину пропущенное поле с пустой пустой строкой ("").

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

Преимущества :

  • Агрегирование терминов будет генерироваться динамически со всеми существующими полями.

  • Для каждого документа, которыйне содержит никаких полей, будет показана пустая строка.

Недостатки :

  • Цикл поРезультат GET mapping API может быть немного разочаровывающим (но я вам доверяю).

  • Производительность (время и ресурсы) будет зависеть от каждого нового поля в ваших сопоставлениях.

Надеюсь, это полезно! : D

...