针对自身对列表字段的重要术语聚合

Significant terms aggregation over a list field against itself

我有以下格式的文档:

{ "my_field": ["foo", "bar", "baz"] }
{ "my_field": ["foo", "baz"] }
{ "my_field": ["foo", "bar"] }

我想找出哪些 my_field 项对最常同时出现。我尝试使用 significant_terms 聚合,例如:

{
    "aggs": {
        "fields": {
            "terms": {"field": "my_field"},
            "aggs": {
                "significant_pairs_with": {
                    "significant_terms": {"field": "my_field"}
                }
            }
        }
    }
}

除了每个聚合中的最高结果是父结果的副本外,这非常有效,例如"foo" 总是与 "foo" 一起出现。有没有办法过滤掉这些?还是我需要不同的聚合?

您可以使用脚本化的启发式评分法将它们过滤掉。类似于:

{
    "aggs": {
        "fields": {
            "terms": {"field": "my_field"},
            "aggs": {
                "significant_pairs_with": {
                    "significant_terms": {
                        "field": "my_field",
                        "script_heuristic": {
                            "script": {
                                "lang": "painless",
                                "source": """
                                if (params._subset_freq == params._subset_size) { 
                                    0 
                                } else { 
                                    1 
                                }"""
                            }
                        }
                    }
                }
            }
        }
    }                   
}

但是,如果您关心结果的相对顺序,那么该启发式方法就太简单了。它过滤掉你不想要的条款,但它对其他所有内容都是持平的。您可以使用 the example from the Elasticsearch documentation 之类的东西,在此处修改为强制转换为 double 以获得更好的结果:

else {
    (double)params._subset_freq / (double)(params._superset_freq - params._subset_freq + 1)
}

我认为理论上您可以使用提供的四个参数重新实现大部分 the built-in heuristics. For most of them you'll want to start with the NXYSignificanceHeuristic base class,它定义了 computeNxys() 方法。

JLH is one of the simplest to re-implement. This Search Nuggets post 更详细地解释了它。用无痛脚本语言编写是相当令人发指的,但我认为这是一个不错的第一近似值:

"source": """
    if (params._subset_freq == params._subset_size 
    || params._superset_size == 0 
    || ((double)params._superset_freq / (double)params._superset_size) == 0) {
        0
    } else {
        (((double)params._subset_freq / (double)params._subset_size) - ((double)params._superset_freq / (double)params._superset_size)) 
        * ((double)(params._subset_freq / (double)params._subset_size) / ((double)params._superset_freq / (double)params._superset_size))
    }
"""