假设我要按第10到20个百分点内的某个字段过滤文档。我想知道是否可以通过一些简单的查询(例如)进行查询{"fieldName":{"percentile": [0.1, 0.2]}}。
{"fieldName":{"percentile": [0.1, 0.2]}}
说我有这些文件:
[{"a":1,"b":101},{"a":2,"b":102},{"a":3,"b":103}, ..., {"a":100,"b":200}]
我需要按a(升序)a 从前10位到第10位进行过滤b,然后按降序对结果进行排序,然后进行分页(如第2页,第10页)每页的项目)。
a
b
想到的一种解决方案是:
获取文件总数。
将文档按排序a,取对应_id的限制0.1 * total_count
_id
0.1 * total_count
写最终查询,像 id in (...) order by b
id in (...) order by b
但是缺点也很明显:
如果我们谈论的是亚秒级延迟,则似乎效率不高
如果我们_id在第一个查询中返回的次数太多(第二个查询默认情况下,ES仅允许1000个,则第二个查询可能不起作用。我当然可以更改配置,但总会有一个限制)。
我怀疑如果a事先不知道的确切值,是否可以在一个查询中执行此操作,尽管我认为一种非常有效的方法是可行的。
我建议做一个percentiles聚合作为第一查询和第二range查询。
percentiles
range
在我的样本索引中,我只有14个文档,因此出于说明性原因,我将尝试查找那些占字段30%到60%的文档,a并按b相反的顺序对它们进行排序(以确保排序有效)。
这是我插入的文档:
{"a":1,"b":101} {"a":5,"b":105} {"a":10,"b":110} {"a":2,"b":102} {"a":6,"b":106} {"a":7,"b":107} {"a":9,"b":109} {"a":4,"b":104} {"a":8,"b":108} {"a":12,"b":256} {"a":13,"b":230} {"a":14,"b":215} {"a":3,"b":103} {"a":11,"b":205}
让我们找出a介于30%和60%百分位数之间的字段边界:
POST my_percent/doc/_search { "size": 0, "aggs" : { "percentiles" : { "percentiles" : { "field" : "a", "percents": [ 30, 60, 90 ] } } } }
用我的样本索引看起来像这样:
{ ... "hits": { "total": 14, "max_score": 0, "hits": [] }, "aggregations": { "percentiles": { "values": { "30.0": 4.9, "60.0": 8.8, "90.0": 12.700000000000001 } } } }
现在我们可以使用边界进行range查询:
POST my_percent/doc/_search { "query": { "range": { "a" : { "gte" : 4.9, "lte" : 8.8 } } }, "sort": { "b": "desc" } }
结果是:
{ "took": 5, "timed_out": false, "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0 }, "hits": { "total": 4, "max_score": null, "hits": [ { "_index": "my_percent", "_type": "doc", "_id": "vkFvYGMB_zM1P5OLcYkS", "_score": null, "_source": { "a": 8, "b": 108 }, "sort": [ 108 ] }, { "_index": "my_percent", "_type": "doc", "_id": "vUFvYGMB_zM1P5OLWYkM", "_score": null, "_source": { "a": 7, "b": 107 }, "sort": [ 107 ] }, { "_index": "my_percent", "_type": "doc", "_id": "vEFvYGMB_zM1P5OLRok1", "_score": null, "_source": { "a": 6, "b": 106 }, "sort": [ 106 ] }, { "_index": "my_percent", "_type": "doc", "_id": "u0FvYGMB_zM1P5OLJImy", "_score": null, "_source": { "a": 5, "b": 105 }, "sort": [ 105 ] } ] } }
注意percentiles聚合的结果是近似的。
通常,这看起来像是通过熊猫或Spark作业可以更好地解决的任务。
希望有帮助!