使用聚合检索查询结果中的术语的文档频率

时间:2014-11-06 14:45:41

标签: elasticsearch

对于我对ElasticSearch的一些查询,我想要回复三条信息:

  • 结果文档集中出现了哪些术语?
  • 结果文档集中每个T元素的出现频率是多少次?
  • T的每个元素在整个索引中出现的频率( - >文档频率)?

使用默认术语facet或现在通过术语聚合方法可以轻松确定第一个点。 所以我的问题实际上是关于第三点。 在ElasticSearch 1.x之前,即在切换到'聚合之前范式,我可以使用“全球”这个术语的一个方面。选项设置为trueQueryFilter,以获取QueryFilter指定的文档集中出现的确切字词的文档频率('全局计数')。 起初我以为我可以使用global aggregation做同样的事情,但似乎我无法做到。原因是 - 如果我理解正确 - 原始facet机制以术语为中心,而聚合桶由属于每个桶的文档集定义。 即使用global指定term facet的{​​{1}}选项首先确定过滤器命中的术语,然后计算构面值。由于方面是QueryFilter,我会收到文件计数。

通过汇总,它有所不同。 global聚合只能用作顶级聚合,导致聚合忽略当前查询结果并计算聚合 - 例如a global - 索引中的所有文档。所以对我而言,这太过分了,因为我想将返回的术语('存储桶')限制为文档结果集中的术语。但是如果我使用带子项聚合的过滤子聚合,我会将术语桶再次限制为过滤器,因此不会检索文档频率而是检索正常的面数。原因是铲斗是在过滤器之后确定的,所以它们太小了#34;但是我不想要限制存储桶大小,我想将存储桶限制为查询结果集中的条件。

如何使用聚合在查询结果集中获取这些术语的文档频率(因为不推荐使用facet并将其删除)?

谢谢你的时间!

编辑:以下是我尝试实现所需行为的示例。 我将定义两个聚合:

  • global_agg_with_filter_and_terms
  • global_agg_with_terms_and_filter

它们的顶部都有一个terms aggregation聚合,因为它是唯一有效的位置。然后,在第一个聚合中,我首先将结果过滤到原始查询,然后应用术语子聚合。 在第二个聚合中,我大致相同,只是在这里,过滤器聚合是术语聚合的子聚合。因此,相似的名称,只有聚合的顺序不同。

global

响应:

{
    "query": {
        "query_string": {
            "query": "text: my query string"
        }
    },
    "aggs": {
        "global_agg_with_filter_and_terms": {
            "global": {},
            "aggs": {
                "filter_agg": {
                    "filter": {
                        "query": {
                            "query_string": {
                                "query": "text: my query string"
                            }
                        }
                    },
                    "aggs": {
                        "terms_agg": {
                            "terms": {
                                "field": "facets"
                            }
                        }
                    }
                }
            }
        },
        "global_agg_with_terms_and_filter": {
            "global": {},
            "aggs": {
                "document_frequency": {
                    "terms": {
                        "field": "facets"
                    },
                    "aggs": {
                        "term_count": {
                            "filter": {
                                "query": {
                                    "query_string": {
                                        "query": "text: my query string"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

首先,请查看两个聚合的前两个返回的术语库,其中包含键{ "took": 18, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 221, "max_score": 0.9839197, "hits": <omitted> }, "aggregations": { "global_agg_with_filter_and_terms": { "doc_count": 1978, "filter_agg": { "doc_count": 221, "terms_agg": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "fid8", "doc_count": 155 }, { "key": "fid6", "doc_count": 40 }, { "key": "fid9", "doc_count": 10 }, { "key": "fid5", "doc_count": 9 }, { "key": "fid13", "doc_count": 5 }, { "key": "fid7", "doc_count": 2 } ] } } }, "global_agg_with_terms_and_filter": { "doc_count": 1978, "document_frequency": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "fid8", "doc_count": 1050, "term_count": { "doc_count": 155 } }, { "key": "fid6", "doc_count": 668, "term_count": { "doc_count": 40 } }, { "key": "fid9", "doc_count": 67, "term_count": { "doc_count": 10 } }, { "key": "fid5", "doc_count": 65, "term_count": { "doc_count": 9 } }, { "key": "fid7", "doc_count": 63, "term_count": { "doc_count": 2 } }, { "key": "fid13", "doc_count": 55, "term_count": { "doc_count": 5 } }, { "key": "fid10", "doc_count": 11, "term_count": { "doc_count": 0 } }, { "key": "fid11", "doc_count": 9, "term_count": { "doc_count": 0 } }, { "key": "fid12", "doc_count": 5, "term_count": { "doc_count": 0 } } ] } } } } fid8。我们可以很容易地看到这些术语分别出现在结果集155和40次中。现在请看第二个聚合fid6。术语聚合在全局聚合的范围内,因此我们实际上可以分别看到文档频率1050和668。所以这部分看起来不错。当您进一步向下扫描术语桶列表时,会出现问题,即使用密钥global_agg_with_terms_and_filterfid10的桶。虽然我们收到他们的文档频率,但我们也可以看到他们的fid12为0.这是因为我们的查询中没有出现这些术语,我们也用于过滤子聚合。所以问题是对于所有术语(全局范围!),返回他们的文档频率和关于实际查询结果的面数。但我需要完全针对查询结果中出现的术语,即第一个聚合term_count返回的确切术语。

也许有可能定义某种类型的过滤器来删除其子过滤器聚合global_agg_with_filter_and_terms为零term_count的所有桶?

1 个答案:

答案 0 :(得分:1)

如果答案迟了,你好,很抱歉。

您应该查看Significant Terms聚合,就像聚合术语一样,它会为结果集中出现的每个术语返回一个存储桶,其中包含doc_count可用的出现次数,但是还可以通过bg_count获取背景集中出现的次数。这意味着它只为出现在查询结果集的文档中的术语创建存储桶。

默认背景集包含查询范围内的所有文档,但可以使用background_filter过滤到您想要的任何子集。

您可以使用脚本式存储桶评分功能,通过组合多个指标,按照您希望的方式对存储桶进行排名:

  • _subset_freq:该术语在结果集中显示的文档数量,
  • _superset_freq:该术语在背景集中出现的文档数量
  • _subset_size:结果集中的文档数量
  • _superset_size:背景集中的文档数量。

请求:

{
  "query": {
    "query_string": {
      "query": "text: my query string"
    }
  },
  "aggs": {
    "terms": {
      "significant_terms": {
        "script": "_subset_freq",
        "size": 100
      }
    }
  }
}