将min_doc_count 与order: ascending 一起使用将无法正常工作,除非。
TL;DR:增加shard_size 和/或shard_min_doc_count 应该可以解决问题。
为什么聚合为空
如documentation所述:
min_doc_count 标准仅在合并本地术语后应用
所有分片的统计信息。
这意味着当您使用带有参数 size 和 min_doc_count 并按降序排列的术语聚合时,Elasticsearch 会检索 size 频率较低的术语在您的数据集中并过滤此列表以仅保留具有 doc_count>min_doc_count 的术语。
如果你想要一个例子,给定这个数据集:
terms | doc_count
----------------
lorem | 3315
ipsum | 2487
olor | 1484
sit | 1057
amet | 875
conse | 684
adip | 124
elit | 86
如果您使用 size=3 和 min_doc_count=100 执行聚合,Elasticsearch 将首先计算 3 个频率较低的术语:
conse: 684
adip : 124
elit : 86
然后过滤doc_count>100,所以最终的结果是:
conse: 684
adip : 124
即使您希望“amet” (doc_count=875) 出现在列表中。 Elasticsearch 在计算结果时会丢失该字段,最终无法检索到它。
如果您的情况是,您有太多带有 doc_count 的术语,以至于它们填满了您的列表,然后在过滤阶段之后,您没有结果。
为什么 Elasticsearch 会这样?
每个人都想应用过滤器,然后对结果进行排序。我们可以使用较旧的数据存储来做到这一点,这很好。但是 Elasticsearch 是为扩展而设计的,所以它默认关闭了一些以前使用的魔法。
为什么?因为对于大型数据集,它会中断。
例如,假设您的索引中有 800,000 个不同的术语,数据分布在不同的分片上(默认为 4 个),可以分布在其他机器上(每个分片最多 1 台机器)。
当请求 doc_count>1000 的词条时,每台机器必须计算数十万个计数器(超过 200,000 个,因为某些词条可能出现在一个分片中,其他出现在另一个分片中,等等)。而且由于即使一个分片只看到一次结果,其他分片也可能已经看到了 999 次,因此在合并结果之前它不能丢弃信息。所以我们需要通过网络发送超过 100 万个计数器。所以它很重,尤其是如果经常这样做的话。
因此,默认情况下,Elasticsearch 将:
- 为每个分片中的每个术语计算
doc_count。
- 不对分片上的 doc_count 应用过滤器(在速度和资源使用方面有所损失,但对准确性更好):否
shard_min_doc_count。
- 将
size * 1.5 + 10 (shard_size) 条款发送到节点。如果顺序是升序,它将是频率较低的术语,否则是最频繁的术语。
- 合并此节点中的计数器。
- 应用
min_doc_count 过滤器。
- 返回
size 出现频率最高/频率最低的结果。
可以简单一次吗?
是的,当然,我说过这种行为是默认的。如果您没有庞大的数据集,您可以调整这些参数:)
解决方案
如果您不满意但准确性有所下降:
-
将shard_size 参数增加到大于[your number of terms with a doc_count below your threshold] + [the number of values you want if you want exact results]。
如果您想要doc_count>=1000 的所有结果,请将其设置为字段的基数(不同术语的数量),但是我看不到order: ascending 的意义。
如果您有很多术语,则会对内存产生巨大影响,如果您有多个 ES 节点,则会影响网络。
如果您没有问题但准确度有所下降(通常是轻微的)
在该总和和[the number of values you want if you want exact results] 之间设置shard_size。如果您想要更快的速度或者如果您没有足够的 RAM 来执行精确的计算,它会很有用。这个值的好坏取决于您的数据集。
使用术语聚合的shard_min_doc_count parameter 部分预过滤频率较低的值。这是一种过滤数据的有效方法,尤其是当它们随机分布在您的分片之间(默认)和/或您没有很多分片时。
您也可以将数据放在一个分片中。在准确性方面没有损失,但对性能和扩展性不利。但是,如果您的数据集较小,您可能不需要 ES 的全部功能。
注意: 术语聚合的降序已被弃用(因为它在时间和硬件方面花费了很多才能准确),将来很可能会被删除。
PS: 你应该添加 Kibana 生成的 Elasticsearch 请求,当 Kibana 返回数据但不是你想要的数据时,它通常很有用?当您单击屏幕截图中图表下方的箭头时,您可以在“请求”选项卡中找到它(例如:http://imgur.com/a/dMCWE)。