重要字段在列表字段上针对自身的聚合

时间:2019-12-23 09:00:39

标签: elasticsearch elasticsearch-aggregation

我有以下格式的文件:

{ "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"一起出现。有没有办法将它们过滤掉?还是我需要其他汇总?

1 个答案:

答案 0 :(得分:1)

您可以使用脚本化的得分启发法将其过滤掉。像这样:

{
    "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的大部分。对于大多数应用程序,您需要以the NXYSignificanceHeuristic base class开始,它定义了computeNxys()方法。

JLH是最简单的重新实现之一。 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))
    }
"""