使用NEST在Elasticsearch中聚合通用嵌套数组

时间:2015-06-24 12:01:49

标签: elasticsearch aggregation nest

我正在尝试使用Elasticsearch分析数据。大约四个月前我开始使用Elasticsearch和Nest,所以我可能错过了一些明显的东西。所有示例都被简化或更改,但核心是相同的。

数据包含一组嵌套对象,每个嵌套对象也包含一组嵌套对象,并且每个嵌套对象都包含一组嵌套对象。数据是从包含XML消息的信息请求中获得的。解析消息,并保存包含(多个)文本元素的每个元素及其元素名称,位置和包含消息名称下所有文本元素名称和值的数组。我认为这种设置可能会使分析数据变得更容易 映射示例:

{
    "data" : {
        "properties" : {
            "id" : { "type" : "string" },
            "action" : { "type" : "string" },
            "result" : { "type" : "string" },
            "details" : {
                "type" : "nested",
                "properties" : {
                    "description" : { "type" : "string" },
                    "message" : {
                        "type" : "nested",
                        "properties" : {
                            "name" : { "type" : "string" },
                            "nodes" : {
                                "type" : "nested",
                                "properties" : {
                                    "name" : { "type" : "string" },
                                    "value" : { "type" : "string" }
                                }
                            },
                            "source" : { "type" : "string" }
                        }
                    }
                }
            }
        }
    }
}

数据示例:

{
    "id" : "123456789",
    "action" : "GetInformation",
    "result" : "Success",
    "details" : [{
            "description" : "Request",
            "message" : [{
                    "name" : "Body",
                    "source" : "Message|Body",
                    "nodes" : [{
                            "name" : "Action",
                            "value" : "GetInformation"
                        }, {
                            "name" : "Identity",
                            "value" : "1234"
                        }
                    ]
                }
            ]
        }, {
            "description" : "Response",
            "message" : [{
                    "name" : "Object",
                    "source" : "Message|Body|Object",
                    "nodes" : [{
                            "name" : "ID",
                            "value" : "123"
                        }, {
                            "name" : "Name",
                            "value" : "Jim"
                        }
                    ]
                }, {
                    "name" : "Information",
                    "source" : "Message|Body|Information",
                    "nodes" : [{
                            "name" : "Type",
                            "value" : "Birth City"
                        }, {
                            "name" : "City",
                            "value" : "Los Angeles"
                        }
                    ]
                }, {
                    "name" : "Information",
                    "source" : "Message|Body|Information",
                    "nodes" : [{
                            "name" : "Type",
                            "value" : "City of Residence"
                        }, {
                            "name" : "City",
                            "value" : "New York"
                        }
                    ]
                }
            ]
        }
    ]
}

XML示例:

<Message>
    <Body>
        <Object>
            <ID>123</ID>
            <Name>Jim</Name>
        </Object>
        <Information>
            <Type>Birth City</Type>
            <City>Los Angeles</City>
        <Information>
        <Information>
            <Type>City of Residence</Type>
            <City>New York</City>
        <Information>
    </Body>
</Message>

我想分析节点的名称和价值属性,这样我就可以了解作为出生地的索引中的每个城市的概况以及在其中出生的人数。类似的东西:

Dictionary<string, int> birthCities = { 
    {"Los Angeles", 400}, {"New York", 800}, 
    {"Detroit", 500}, {"Michigan", 700} };

到目前为止我的代码:

var response = client.Search<Data>(search => search
    .Query(query => 
        query.Match(match=> match
            .OnField(data=>data.Action)
            .Query("GetInformation")
        )
    )
    .Aggregations(a1 => a1
        .Nested("Messages", messages => messages
            .Path(data => data.details.FirstOrDefault().Message)
            .Aggregations(a2 => a2
                .Terms("Sources", termSource => termSource
                    .Field(data => data.details.FirstOrDefault().Message.FirstOrDefault().Source)
                    .Aggregations(a3 => a3
                        .Nested("Nodes", nodes => nodes
                            .Path(dat => data.details.FirstOrDefault().Message.FirstOrDefault().Nodes)
                            .Aggregations(a4 => a4
                                .Terms("Names", termName => termName
                                    .Field(data => data.details.FirstOrDefault().Message.FirstOrDefault().Nodes.FirstOrDefault().Name)
                                    .Aggregations(a5 => a5
                                        .Terms("Values", termValue => termValue
                                            .Field(data => data.details.FirstOrDefault().Message.FirstOrDefault().Nodes.FirstOrDefault().Value)
                                        )
                                    )
                                )
                            )
                        )
                    )    
                )
            )
        )
    )
);

var dict = new Dictionary<string, long>();
var sAggr = response.Aggs.Nested("Messages").Terms("Sources");
foreach (var item in sAggr.Items)
{
    if (item.Key.Equals("information"))
    {
        var nAggr = item.Nested("Nodes").Terms("Names");
        foreach (var nItem in nAggr.Items)
        {
            if (nItem.Key.Equals("city"))
            {
                var vAgg = nItem.Terms("Values");
                foreach (var vItem in vAgg.Items)
                {
                    if (!dict.ContainsKey(vItem.Key))
                    {
                        dict.Add(vItem.Key, 0);
                    }
                    dict[vItem.Key] += vItem.DocCount;
                }
            }
        }
    }
}

此代码为我提供了每个城市及其出现次数,但由于它们使用相同的元素名称保存在同一位置(两者都无法更改),我发现没有区分出生城市和居住城市的方法。

遗憾的是,每个动作的特定类型都不是一种选择。所以我的问题是:如何计算出生城市类型的所有城市名称,最好不必导入和浏览所有文件。

0 个答案:

没有答案