【问题标题】:Is it possible to perform elasticsearch nested stats aggregation on a field defined by the parent aggregation?是否可以对父聚合定义的字段执行弹性搜索嵌套统计聚合?
【发布时间】:2015-11-03 04:30:24
【问题描述】:

我正在尝试进行查询以生成绘图。我的数据索引如下所示:

"mappings": {
    "mydata": {
        "properties": {
            "type": { "type": "string", "index": "not_analyzed" },
            "stamp": { "type": "date", "format": "date_hour_minute_second_millis" },
            "data": { "type": "object" }
        }
    }

根据类型,数据字段将包含不同的对象,例如,

temperature_data = {
    "type": "temperature",
    "stamp": "2015-11-01T15:25:19.123",
    "data": {"temperature": 23.4, "variance": 0.0}
}
humidity_data = {
    "type": "humidity",
    "stamp": "2015-11-01T15:26:21.063",
    "data": {"humidity": 75.1, "variance": 0.0}
}

我正在尝试根据桶的类型汇总桶中的数据,然后执行日期直方图以获取每个读数(温度、湿度)的统计信息。我的问题是如何在 stats aggs 上设置字段,因为它随类型而变化(例如,"type": "temperature" 字段为 data.temperature):

query = {
    "size": 0,
    "query": {
        "filtered": {
            "filter": {
                "bool": {
                    "must": [
                        {"range" : {
                            "stamp" : {
                                "gt" : start_stamp,
                                "lt" : end_stamp
                            }
                        }}
                    ]
                }
            }
        }
    },
    "aggs": {
        "pathes": {
            "terms": {
                "field": "type"
            },
            "aggs": {
                "points": {
                    "date_histogram": {
                        "field": "stamp",
                        "interval": interval
                    },
                    "aggs": {
                        "point_stats": {
                            "stats": {
                                "field": "data."+field???
                            }
                        }
                    }
                }
            }
        }
    }
}

* 更新 *

按照建议,我在 config/scripts/ 中添加了一个 data-type.groovy 文件,该文件包含以下内容:

return doc['data.temperature'].value

Elasticsearch 能够编译脚本:

[2015-11-02 19:50:32,651][INFO ][script] [Atum] compiling script file [/home/user/elasticsearch-1.7.0/config/scripts/data-type.groovy]

我更新了查询以加载脚本文件:

query = {
    "size": 0,
    "query": {
        "filtered": {
            "filter": {
                "bool": {
                    "must": [
                        {"range" : {
                            "stamp" : {
                                "gt" : start_stamp,
                                "lt" : end_stamp
                            }
                        }}
                    ]
                }
            }
        }
    },
    "aggs": {
        "pathes": {
            "terms": {
                "field": "type"
            },
            "aggs": {
                "points": {
                    "date_histogram": {
                        "field": "stamp",
                        "interval": interval
                    },
                    "aggs": {
                        "point_stats": {
                            "stats": {
                                "script": {"file": "data-type"}
                            }
                        }
                    }
                }
            }
        }
    }
}

当我运行查询时,我得到以下输出:

{u'status': 400, u'error': u'SearchPhaseExecutionException[Failed to execute phase [query], ... Parse Failure [Unexpected token START_OBJECT in [point_stats].]]; }]'}

数据库中只有温度数据,如果我将 "script": {"file": "data-type"} 更改为 "field": "data.temperature" 查询有效。

【问题讨论】:

    标签: elasticsearch plot statistics


    【解决方案1】:

    一种选择是将humiditytemperature 字段重命名为相同的名称,例如value,这样您就可以简单地在该字段上进行聚合,就可以了。从type 字段中您已经知道它是什么类型的值。

    "aggs": {
        "pathes": {
            "terms": {
                "field": "type"
            },
            "aggs": {
                "points": {
                    "date_histogram": {
                        "field": "stamp",
                        "interval": interval
                    },
                    "aggs": {
                        "point_stats": {
                            "stats": {
                                "field": "data.value"
                            }
                        }
                    }
                }
            }
        }
    }
    

    第二种选择是使用script,但如果您要添加更多类型的数据(压力等),那么性能和可扩展性都会降低

    "aggs": {
        "pathes": {
            "terms": {
                "field": "type"
            },
            "aggs": {
                "points": {
                    "date_histogram": {
                        "field": "stamp",
                        "interval": interval
                    },
                    "aggs": {
                        "point_stats": {
                            "stats": {
                                "script": "return doc.type.value == 'temperature' ? doc['data.temperature'].value : doc['data.humidity'].value"
                            }
                        }
                    }
                }
            }
        }
    }
    

    请注意,对于第二个选项,您需要 enable dynamic scripting

    【讨论】:

    • 感谢您的回答,我试图避免对保存实际标量值的字段使用相同的命名,因为不同的传感器将具有不同的结构,因此 som 甚至可能没有标量值。我将研究这两个选项,但我会尽量避免使用自定义脚本!
    • 哦,我明白了。您仍然可以使用不同的字段名称,但创建另一个具有标量值(适用的情况)的字段名称,您可以将其仅用于聚合。
    • 你可以用脚本文件做同样的事情,而不是使用内联脚本吗?
    • 是的,当然,您只需要将脚本放在config/scripts/ 文件夹内的文件中,使用"file": "script_name" 引用它,它将在启动时加载。
    • 我以前做过脚本文件,但这似乎不起作用。我将 data-type.groovy 文件添加到 config/scripts/,它是由 ES 加载的。我在文件中的所有内容都是返回 doc['data.temperature'].value。如果我使用 "stats": {"field": "data.temperature"} 运行查询,它可以工作,如果我将其更改为 "stats": {"script": {"file": "data-type"}}我在 [point_stats] 中收到错误 Unexpected token START_OBJECT。我错过了什么吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-06
    • 1970-01-01
    相关资源
    最近更新 更多