如何通过Elasticsearch 6.x中的动态或未知字段进行聚合

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何通过Elasticsearch 6.x中的动态或未知字段进行聚合相关的知识,希望对你有一定的参考价值。

我是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
            ]
        ]
    ]

    // ...
]

任何人都可以提供的任何见解将非常感激。

答案

您应该在您的php脚本中执行此操作。

我可以想到以下内容:

  1. 使用Dynamic field mapping作为索引。

默认情况下,当在文档中找到以前看不见的字段时,Elasticsearch会将新字段添加到类型映射中。通过将dynamic参数设置为false(忽略新字段)或strict(如果遇到未知字段,则引发异常),可以在文档和对象级别禁用此行为。

  1. 获取索引中的所有现有字段。为此使用Get mapping API

  • 遍历步骤2的结果,因此您可以获取索引中的所有现有字段。例如,您可以将它们存储在列表(或数组)中。

  • 您可以为列表(或数组)中的每个字段创建一个PHP Elasticsearch terms aggregation。这是:创建一个不带任何术语聚合的空查询或基本查询,并为从步骤3中获得的每个元素添加一个术语。

  • 将每个missing field添加到一个空字符串(“”)。

  • 就这样。之后,您将以这种方式创建查询,无论您要搜索的是什么索引,您都将获得包含所有现有字段的术语集合。

  • 优势:

    • 您的条件聚合将与所有现有字段一起动态生成。

    • 对于每个不包含任何字段的文档,将显示一个空字符串。

    • 缺点]::

    • 遍历GET映射API的结果可能会有些令人沮丧(但我相信您)。

    • 性能(时间和资源)将影响您在映射中找到的每个新字段。

    • 我希望这会有所帮助! :D

    以上是关于如何通过Elasticsearch 6.x中的动态或未知字段进行聚合的主要内容,如果未能解决你的问题,请参考以下文章

    「日记」ElasticSearch7.x新功能介绍

    Elasticsearch:Dynamic field mapping

    ElasticSearch——索引生命周期管理

    安装elasticsearch 5.x, 6.x 常见问题(坑)的解决

    安装elasticsearch 5.x, 6.x 常见问题(坑)的解决

    干货 | Elasticsearch 8.X 版本升级指南