【问题标题】:Grouping ElasticSearch documents on xml tag value (in a string field)根据 xml 标记值对 ElasticSearch 文档进行分组(在字符串字段中)
【发布时间】:2016-08-26 21:20:13
【问题描述】:

我的 ElasticSearch 索引中有此类文档:

{
    "took" : 31,
    "timed_out" : false,
    "_shards" : {
        "total" : 68,
        "successful" : 68,
        "failed" : 0
    },
    "hits" : {
        "total" : 9103,
        "max_score" : 8.823501,
        "hits" : [{
                "_index" : "ESB",
                "_type" : "MDOrderFO",
                "_id" : "AVaxDzEGBclOg4W8YiW1",
                "_score" : 8.823501,
                "_source" : {
                    "message" : "<root><flux>MyFlux</flux><requestId>123</requestId><timeStamp>2016-26-08T09:37:17</timeStamp><step>1</step><status>ok</status><body><xml><myobject><field1>value1</field1></myobject></xml></body></root>",
                    "timestamp" : "2016-08-22T07:02:57.085Z",
                    "logger_name" : "MDOrderFOToFO"
                }
            }, {
                "_index" : "ESB",
                "_type" : "MDOrderFO",
                "_id" : "AVaxDzEGBclOg4W8YiW1",
                "_score" : 8.823501,
                "_source" : {
                    "message" : "<root><flux>MyFlux</flux><requestId>123</requestId><timeStamp>2016-26-08T09:37:17</timeStamp><step>2</step><status>ok</status><body><xml><myobject><field1>value1</field1></myobject></xml></body></root>",
                    "timestamp" : "2016-08-22T07:02:57.085Z",
                    "logger_name" : "MDOrderFOToFO"
                }
            }, {
                "_index" : "ESB",
                "_type" : "MDOrderFO",
                "_id" : "AVaxDzEGBclOg4W8YiW1",
                "_score" : 8.823501,
                "_source" : {
                    "message" : "<root><flux>MyFlux</flux><requestId>123</requestId><timeStamp>2016-26-08T09:37:18</timeStamp><step>3</step><status>ok</status><body><xml><myobject><field1>value1</field1></myobject></xml></body></root>",
                    "timestamp" : "2016-08-22T07:02:57.085Z",
                    "logger_name" : "MDOrderFOToFO"
                }
            }, {
                "_index" : "ESB",
                "_type" : "MDOrderFO",
                "_id" : "AVaxDzEGBclOg4W8YiW1",
                "_score" : 8.823501,
                "_source" : {
                    "message" : "<root><flux>MyFlux</flux><requestId>123</requestId><timeStamp>2016-26-08T09:37:26</timeStamp><step>1</step><status>ok</status><body><xml><myobject><field1>value1</field1></myobject></xml></body></root>",
                    "timestamp" : "2016-08-22T07:02:57.085Z",
                    "logger_name" : "MDOrderFOToFO"
                }
            }, {
                "_index" : "ESB",
                "_type" : "MDOrderFO",
                "_id" : "AVaxDzEGBclOg4W8YiW1",
                "_score" : 8.823501,
                "_source" : {
                    "message" : "<root><flux>MyFlux</flux><requestId>456</requestId><timeStamp>2016-26-08T09:37:27</timeStamp><step>2</step><status>ok</status><body><xml><myobject><field1>value1</field1></myobject></xml></body></root>",
                    "timestamp" : "2016-08-22T07:02:57.085Z",
                    "logger_name" : "MDOrderFOToFO"
                }
            }, {
                "_index" : "ESB",
                "_type" : "MDOrderFO",
                "_id" : "AVaxDzEGBclOg4W8YiW1",
                "_score" : 8.823501,
                "_source" : {
                    "message" : "<root><flux>MyFlux</flux><requestId>456</requestId><timeStamp>2016-26-08T09:37:27</timeStamp><step>3</step><status>ok</status><body><xml><myobject><field1>value1</field1></myobject></xml></body></root>",
                    "timestamp" : "2016-08-22T07:02:57.085Z",
                    "logger_name" : "MDOrderFOToFO"
                }
            }, {
                "_index" : "ESB",
                "_type" : "MDOrderFO",
                "_id" : "AVaxDzEGBclOg4W8YiW1",
                "_score" : 8.823501,
                "_source" : {
                    "message" : "<root><flux>MyFlux</flux><requestId>456</requestId><timeStamp>2016-26-08T09:37:17</timeStamp><step>2</step><status>ok</status><body><xml><myobject><field1>value1</field1></myobject></xml></body></root>",
                    "timestamp" : "2016-08-22T07:02:57.085Z",
                    "logger_name" : "MDOrderFOToFO"
                }
            }
        ]
    }
}

这里是消息字段的XML格式:

<root>
    <flux>MyFlux</flux>
    <requestId>123</requestId>
    <timeStamp>2016-26-08T09:37:17</timeStamp>
    <step>2</step>
    <status>ok</status>
    <body><xml><myobject><field1>value1</field1></myobject></xml></body>
</root>

我想构建一个查询,可以根据 RequestId 值(在消息字段的 XML 内容中)对我的文档进行分组。 我期待这样的答案:

{
    "took" : 31,
    "timed_out" : false,
    "_shards" : {
        "total" : 68,
        "successful" : 68,
        "failed" : 0
    },
    "hits" : {
        "total" : 9103,
        "max_score" : 8.823501,
        "hits" : [...],
        "aggregations" : {
            "myaggs" : {
                "doc_count_error_upper_bound" : 0,
                "sum_other_doc_count" : 0,
                "buckets" : [{
                        "key" : "123",
                        "documents" : [{
                                "_index" : "ESB",
                                "_type" : "MDOrderFO",
                                "_id" : "AVaxDzEGBclOg4W8YiW1",
                                "_score" : 8.823501,
                                "_source" : {
                                    "message" : "<root><flux>MyFlux</flux><requestId>123</requestId><timeStamp>2016-26-08T09:37:17</timeStamp><step>1</step><status>ok</status><body><xml><myobject><field1>value1</field1></myobject></xml></body></root>",
                                    "timestamp" : "2016-08-22T07:02:57.085Z",
                                    "logger_name" : "MDOrderFOToFO"
                                }
                            }, {
                                "_index" : "ESB",
                                "_type" : "MDOrderFO",
                                "_id" : "AVaxDzEGBclOg4W8YiW1",
                                "_score" : 8.823501,
                                "_source" : {
                                    "message" : "<root><flux>MyFlux</flux><requestId>123</requestId><timeStamp>2016-26-08T09:37:17</timeStamp><step>2</step><status>ok</status><body><xml><myobject><field1>value1</field1></myobject></xml></body></root>",
                                    "timestamp" : "2016-08-22T07:02:57.085Z",
                                    "logger_name" : "MDOrderFOToFO"
                                }
                            }, {
                                "_index" : "ESB",
                                "_type" : "MDOrderFO",
                                "_id" : "AVaxDzEGBclOg4W8YiW1",
                                "_score" : 8.823501,
                                "_source" : {
                                    "message" : "<root><flux>MyFlux</flux><requestId>123</requestId><timeStamp>2016-26-08T09:37:18</timeStamp><step>3</step><status>ok</status><body><xml><myobject><field1>value1</field1></myobject></xml></body></root>",
                                    "timestamp" : "2016-08-22T07:02:57.085Z",
                                    "logger_name" : "MDOrderFOToFO"
                                }
                            }
                        ]
                    }, {
                        "key" : "456",
                        "documents" : [{
                                "_index" : "ESB",
                                "_type" : "MDOrderFO",
                                "_id" : "AVaxDzEGBclOg4W8YiW1",
                                "_score" : 8.823501,
                                "_source" : {
                                    "message" : "<root><flux>MyFlux</flux><requestId>123</requestId><timeStamp>2016-26-08T09:37:26</timeStamp><step>1</step><status>ok</status><body><xml><myobject><field1>value1</field1></myobject></xml></body></root>",
                                    "timestamp" : "2016-08-22T07:02:57.085Z",
                                    "logger_name" : "MDOrderFOToFO"
                                }
                            }, {
                                "_index" : "ESB",
                                "_type" : "MDOrderFO",
                                "_id" : "AVaxDzEGBclOg4W8YiW1",
                                "_score" : 8.823501,
                                "_source" : {
                                    "message" : "<root><flux>MyFlux</flux><requestId>456</requestId><timeStamp>2016-26-08T09:37:27</timeStamp><step>2</step><status>ok</status><body><xml><myobject><field1>value1</field1></myobject></xml></body></root>",
                                    "timestamp" : "2016-08-22T07:02:57.085Z",
                                    "logger_name" : "MDOrderFOToFO"
                                }
                            }, {
                                "_index" : "ESB",
                                "_type" : "MDOrderFO",
                                "_id" : "AVaxDzEGBclOg4W8YiW1",
                                "_score" : 8.823501,
                                "_source" : {
                                    "message" : "<root><flux>MyFlux</flux><requestId>456</requestId><timeStamp>2016-26-08T09:37:27</timeStamp><step>3</step><status>ok</status><body><xml><myobject><field1>value1</field1></myobject></xml></body></root>",
                                    "timestamp" : "2016-08-22T07:02:57.085Z",
                                    "logger_name" : "MDOrderFOToFO"
                                }
                            }, {
                                "_index" : "ESB",
                                "_type" : "MDOrderFO",
                                "_id" : "AVaxDzEGBclOg4W8YiW1",
                                "_score" : 8.823501,
                                "_source" : {
                                    "message" : "<root><flux>MyFlux</flux><requestId>456</requestId><timeStamp>2016-26-08T09:37:17</timeStamp><step>2</step><status>ok</status><body><xml><myobject><field1>value1</field1></myobject></xml></body></root>",
                                    "timestamp" : "2016-08-22T07:02:57.085Z",
                                    "logger_name" : "MDOrderFOToFO"
                                }
                            }
                        ]
                    }
                ]
            }
        }
    }
}

我是 ElasticSearch 的新手,我花了一周的时间在这上面……而此时,我什至不知道这是否可能。

我真的希望你能帮助我。 提前谢谢你。

当然,作为一个说法语的人,对不起我的英语

编辑
- 不幸的是我无法编辑映射。我无权访问将日志保存到 E.S. 的部分过程
- 实际上,我给出的格式在现实中是非常简单的。在映射级别和 XML 内容中记录了许多其他技术信息。 上下文:将日志推送到 E.S. 的 BUS 应用程序。有3个步骤(1:接收,2:路由,3:发送)。它记录有关请求状态(正常、失败)和在此请求中传输的对象的信息。 我正在处理的应用程序的目的是显示有关已过境的所有请求的业务信息,即某个日期范围的 BUS 应用程序。
所以在我的查询中,我想:
1. 按 RequestId 聚合我的日志(每个组应在接收步骤包含 1 个日志,在路由步骤包含 0 或 1 个日志,在发送步骤包含 0 或 1 个日志)
2. 在接收步骤中过滤日志日期的结果组
3. 取前10组按日期降序排列

【问题讨论】:

    标签: json xml elasticsearch aggregate


    【解决方案1】:

    实现此目的的一种方法是修改您的数据库架构。由于您的 xml 架构是固定的,您可以将每个 xml 节点存储在 Elastic 中的单独字段中,而不是将整个 xml 存储在单个字段中。例如flux,requestId,timeStamp 等将映射到 Elastic 中的单独字段(可能同名)。

    【讨论】:

    • 感谢您的回答,但就像我在编辑中所说的那样:我无法更改映射:/
    【解决方案2】:

    我不是 100% 确定你想在这里实现什么,所以我会尝试指出一些你可以考虑和/或尝试的事情:

    无论您要实现什么目标,您在 ES 索引中存储数据的方式对查询都不是很友好。 我建议打破您的 XML 文档并将每个属性存储在单独的字段中,如下所示:

    "_source" : {
        "flux": "My Flux",
        "requestId": 123,
        "xml_timeStamp": "2016-26-08T09:37:17",
        "step": 1,
        "status": "ok",
        "field1": "value1",
        "timestamp" : "2016-08-22T07:02:57.085Z",
        "logger_name" : "MDOrderFOToFO"
    }
    

    这种存储数据的方式意味着您只需要使用value count aggregation 进行聚合。

    为了实现这一点,您可能需要一种方法来破坏您的 XML 文档并将其映射到这个新的 ElasticSearch 映射。

    在这种情况下,您的聚合查询类似于:

    {
        "aggs" : {
            "myaggs" : {
                "avg_price" : { "value_count" : { "field" : "requestId" } }
            }
        }
    }
    

    如果您无法更新索引映射,我建议您查看 regex filtering 并将其包含在聚合查询中。

    无论哪种方式,aggregations 都不会将每个存储桶内的文档返回给您。要返回 Elasticsearch 或任何其他类型的数据库中的所有文档,没有好的用例。这将是一个非常占用内存的操作,而且速度也很慢。

    如果您希望您的文档按requestId 的顺序返回,那么请考虑将索引映射更改为我上面建议的那个。然后使用sort返回你的数据。

    如果这有帮助,请告诉我:)

    【讨论】:

    • 感谢您的回答,但就像我在编辑中所说的那样:我无法更改映射:/
    • 那么,如果我设法在第一步中使用 RegExp 对 RequestId 进行聚合,我应该首先查询每个返回的 RequestId 吗?
    • 取决于您想要实现的目标。如果您需要按requestId 排序的所有文档的列表,那么只需使用我提到的sort。如果您需要具有特定 requestId 的所有文档,请使用 regex 查询来提取这些文档。
    • 从您的示例看来,您似乎想要所有文档,按requestId 排序,所以我不确定为什么要聚合部分。如果我的理解是错误的,您能否添加另一个编辑,指定最终结果应该是什么?谢谢
    • 我已经编辑了我的帖子来解释我的需求(以及上下文让你很好地理解)。我希望你能更好地理解。如果我在做我想做的事时走错路了,请随时告诉我。
    猜你喜欢
    • 2020-09-20
    • 2021-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多