使用ElasticSearch的聚合删除重复文档

时间:2017-04-25 09:17:57

标签: elasticsearch groovy

我在Elastic中有这三个文档,如下所示,

{
    "@timestamp": "2017-04-20T09:01:55.232Z",
    "outer": {
        "sequence": "44304",
        "reference": "1.2.3.4",
        "inner": {
            "first": {
                "reference": "moduleA",
                "identity": "mouduleA-alarm"
            }
        }
    }
}

{
    "@timestamp": "2017-04-20T09:01:54.232Z",
    "outer": {
        "sequence": "44304",
        "reference": "1.2.3.4",
        "inner": {
            "first": {
                "reference": "moduleA",
                "identity": "mouduleA-alarm"
            }
        }
    }
}

{
    "@timestamp": "2017-04-20T09:01:57.232Z",
    "outer": {
        "sequence": "44304",
        "reference": "1.2.3.4",
        "inner": {
            "second": {
                "reference": "moduleA",
                "identity": "mouduleA-alarm"
            }
        }
    }
}

我正在对这些文档运行查询,然后聚合它们。在聚合中,基于三个字段移除重复文档。 查询如下:

{
    "aggs": {
        "dedup": {
            "terms": {  
                "script":"[doc['outer.reference'].value, doc['outer.inner.first.reference'].value, doc['outer.inner.first.identity'].value].join('_')",
                "lang": "groovy",
                "valueType": "string"
            },
            "aggs": {
                "dedup_docs": {
                    "top_hits": {
                        "size": 1
                    }
                }
            }
        }
    }
}

以上查询工作正常,但问题是内部块内的容器名称是动态的,即它们可以第一个第二个依此类推。但我需要访问内部块中的引用标识以进行聚合。

我尝试在脚本中使用正则表达式,但没有成功。

{
    "aggs": {
        "dedup": {
            "terms": {  
                "script":"[doc['outer.reference'].value, doc[/'outer.inner..+.reference'/].value, doc[/'outer.inner..+.identity'/].value].join('_')",
                "lang": "groovy",
                "valueType": "string"
            },
            "aggs": {
                "dedup_docs": {
                    "top_hits": {
                        "size": 1
                    }
                }
            }
        }
    }
}

以上查询抛出未找到值的异常。

注意:Elastic中的映射是动态模板,所有字段都是非分析的。

感谢。

2 个答案:

答案 0 :(得分:1)

在您的脚本中,您可以找到第一个键,然后动态使用它

这样的事情应该做:

def array = [doc['outer.reference'].value]; 
def key = doc['outer.inner'].keySet().iterator.next();
array << doc['outer.inner'][key]['reference'].value;
array << doc['outer.inner'][key]['identity'].value;
return array.join('_')

答案 1 :(得分:0)

这对我有用

def array = [_source.outer.reference]; 
def key = _source.outer.inner.keySet().iterator.next();
array << _source.outer.inner[key]['reference'];
array << _source.outer.inner[key]['identity'];
return array.join('_')

使用 doc 未返回容器值的JSON,但使用 _source

感谢Val的帮助。