Alf*_*lfe 9 search nested aggregate duplicates elasticsearch
我试图在我的数据中找到在多个方面相同的条目.我目前使用嵌套聚合的复杂查询来执行此操作:
{
"size": 0,
"aggs": {
"duplicateFIELD1": {
"terms": {
"field": "FIELD1",
"min_doc_count": 2 },
"aggs": {
"duplicateFIELD2": {
"terms": {
"field": "FIELD2",
"min_doc_count": 2 },
"aggs": {
"duplicateFIELD3": {
"terms": {
"field": "FIELD3",
"min_doc_count": 2 },
"aggs": {
"duplicateFIELD4": {
"terms": {
"field": "FIELD4",
"min_doc_count": 2 },
"aggs": {
"duplicate_documents": {
"top_hits": {} } } } } } } } } } } }
Run Code Online (Sandbox Code Playgroud)
这在某种程度上起作用,因为当没有找到重复项时,我得到的结果如下所示:
{
"took" : 5,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"failed" : 0
},
"hits" : {
"total" : 27524067,
"max_score" : 0.0,
"hits" : [ ]
},
"aggregations" : {
"duplicateFIELD1" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 27524027,
"buckets" : [
{
"key" : <valueFromField1>,
"doc_count" : 4,
"duplicateFIELD2" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : <valueFromField2>,
"doc_count" : 2,
"duplicateFIELD3" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : <valueFromField3>,
"doc_count" : 2,
"duplicateFIELD4" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [ ]
}
}
]
}
},
{
"key" : <valueFromField2>,
"doc_count" : 2,
"duplicateFIELD3" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : <valueFromField3>,
"doc_count" : 2,
"duplicateFIELD4" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [ ]
}
}
]
}
}
]
}
},
{
"key" : <valueFromField1>,
"doc_count" : 4,
"duplicateFIELD2" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : <valueFromField2>,
"doc_count" : 2,
"duplicateFIELD3" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : <valueFromField3>,
"doc_count" : 2,
"duplicateFIELD4" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [ ]
}
}
]
}
},
{
"key" : <valueFromField2>,
"doc_count" : 2,
"duplicateFIELD3" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : <valueFromField3>,
"doc_count" : 2,
"duplicateFIELD4" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [ ]
}
}
]
}
}
]
}
},
...
Run Code Online (Sandbox Code Playgroud)
我正在跳过一些看似相似的输出.
我现在可以浏览这个复杂的深层嵌套数据结构,发现所有这些嵌套存储桶中都没有存储任何文档.但这看起来相当麻烦.我想可能有一种更好(更直接)的做法.
此外,如果我想检查超过四个字段,这个嵌套结构将增长,增长和增长.所以它不能很好地扩展,我想避免这种情况.
我可以改进我的解决方案,以便获得所有重复文档的简单列表吗?(也许那些彼此重复的东西以某种方式组合在一起.)或者是否存在完全不同的方法(例如没有聚合),这没有我在这里描述的缺点?
编辑:我在这里找到了一种使用ES的脚本功能的方法,但是在我的ES版本中,这只返回一条错误消息.也许有人可以向我指出如何在ES 5.0中做到这一点?到目前为止,我的试验没有奏效.
编辑:我找到了一种方法,使用脚本为我的方法使用现代方式(语言"无痛"):
{
"size": 0,
"aggs": {
"duplicateFOO": {
"terms": {
"script": {
"lang": "painless",
"inline": "doc['FIELD1'].value + doc['FIELD2'].value + doc['FIELD3'].value + doc['FIELD4'].value"
},
"min_doc_count": 2
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这似乎是非常少量的数据和结果在现实的数据错误的工作(circuit_breaking_exception
:[request] Data too large, data for [<reused_arrays>] would be larger than limit of [6348236390/5.9gb]
).关于如何解决这个问题的任何想法?可能调整ES的某些配置以使其使用更大的内部缓冲区或类似的?
似乎没有一个适当的解决方案可以避免以一般方式嵌套.
幸运的是,我的四个领域中有三个领域的价值范围非常有限; 第一个只能是1或2,第二个可以是1,2或3,第三个可以是1,2,3或4.由于这些只有24种组合,我现在可以过滤掉一个完整的第24个应用聚合之前的数据集,然后只有一个(剩余的第四个字段).然后,我必须将所有动作应用24次(上述三个有限字段的每个组合一次),但这比一次处理完整数据集更可行.
我现在发送的查询(即24个查询中的一个)看起来像这样:
{
"size": 0,
"query": {
"bool": {
"must": [
{ "match": { "FIELD1": 2 } },
{ "match": { "FIELD2": 3 } },
{ "match": { "FIELD3": 4 } } ] } },
"aggs": {
"duplicateFIELD4": {
"terms": {
"field": "FIELD4",
"min_doc_count": 2 } } } }
Run Code Online (Sandbox Code Playgroud)
当然,结果不再嵌套了.但是,如果多个字段包含较大范围的任意值,则无法执行此操作.
我还发现,如果必须进行嵌套,具有最有限值范围的字段(例如,只有两个值,如"1或2")应该在最里面,而具有最大值范围的字段应该在最外面.这大大提高了性能(但在我的情况下仍然不够).做错了会让你最终得到一个无法使用的查询(几小时内没有响应,最后在服务器端没有内存).
我现在认为正确聚合是解决像我这样的问题的关键.使用脚本具有平坦的桶列表(如我的问题中所述)的方法必然会使服务器过载,因为它无法以任何方式分发任务.在根本没有找到double的情况下,它必须为内存中的每个文档保存一个桶(其中只有一个文档).即使只能找到几个双打,也无法对较大的数据集进行此操作.如果没有别的办法,就需要人为地将数据集拆分成组.E. g.一个人可以通过构建相关字段中的散列来创建16个子数据集,并使用最后4位将文档放入16个组中.然后可以单独处理每个组; 使用这种技术,双打必然会分成一组.
但是,与这些一般性的想法无关,ES API应该提供任何手段来对聚合结果进行分页.遗憾的是,还没有这样的选择.
一个可能适用于 Logstash 场景的想法是使用复制字段:
将所有组合复制到单独的字段并将它们连接起来:
mutate {
add_field => {
"new_field" => "%{oldfield1} %{oldfield2}"
}
}
Run Code Online (Sandbox Code Playgroud)
聚合新字段。
看看这里:https ://www.elastic.co/guide/en/logstash/current/plugins-filters-mutate.html
我不知道 add_field 是否支持数组(如果你查看文档,其他人会支持数组)。如果没有,您可以尝试添加几个新字段并使用合并来只有一个字段。
如果你能在索引时做到这一点,那肯定会更好。
您只需要组合 (A_B) 而不是所有排列 (A_B, B_A)