Mongodb 聚合以获取数组中键值对的总数,并根据类似名称的字段值进行分组
我有如下结构的文档,其中每个数组元素都包含“n”和“v”作为不同类型数据的键和值。我需要按“ipaddress”的“n”值对其进行分组,并计算集合中的全部不同组合。但是,值相似但不相同。(例如:ip、ip地址和ip地址) 查询选择条件如下:Mongodb 聚合以获取数组中键值对的总数,并根据类似名称的字段值进行分组,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我有如下结构的文档,其中每个数组元素都包含“n”和“v”作为不同类型数据的键和值。我需要按“ipaddress”的“n”值对其进行分组,并计算集合中的全部不同组合。但是,值相似但不相同。(例如:ip、ip地址和ip地址) 查询选择条件如下: 如果“loc”为“NW”且“logtype”为“1”,则“ipaddress”=“ip” 如果“loc”为“NW”且“logtype”为“2”,则“ipaddress”=“ip地址” 如果“loc”为“NW”且“logtype”为“3”,则“ipaddres
{"ipaddress" : "2.2.2.2" , count : 1}
{"ipaddress" : "1.1.1.1" , count : 2}
这就是我到目前为止所做的:
db.final.aggregate([
{ "$match": {
"$and": [
{"props" : {"$elemMatch": { "n": "port", "v": "53" }}},
{"props" : {"$elemMatch": { "n": "pro", "v": {"$in" : [/udp/, /tcp/]} }}}
]
}},
{ "$unwind": "$props" },
{
"$project": {
"_ipaddress": {
"$cond": {
"if": { "$eq": [ "$props.n", "ip" ] },
"then": "$props.v",
"else": {
"$cond": {
"if": { "$eq": [ "$props.n", "ip_addr" ] },
"then": "$props.v",
"else": {
"$cond" : {
"if": { "$eq": [ "$props.n", "ipaddr" ] },
"then": "$props.v",
"else" : 0
}
}
}
}
}
},
"_id": 1,
"props" : 1
}
},
{ "$group": {
"_id": "$_id",
"_ipaddress": {
"$min": {
"$cond": [ { "$ne": [ "$_ipaddress", 0 ] }, "$_ipaddress", false ]
}
},
"pro": {
"$min": {
"$cond": [ { "$eq": [ "$props.n", "pro" ] }, "$props.v", false ]
}
},
"logtype": {
"$min": {
"$cond": [ { "$eq": [ "$props.n", "logtype" ] }, "$props.v", false ]
}
},
"port": {
"$min": {
"$cond": [ { "$eq": [ "$props.n", "port" ] }, "$props.v", false ]
}
}
} },
{ "$group": {
"_id": {
"_ipaddress": "$_ipaddress",
},
"count": { "$sum": 1 }
}}
])
但是我不知道如何组合“loc”和“logtype”条件。这里每个文档都有一个数组,用于集中存储相关信息。这种设计不适合您尝试的查询。 据我所知,$unwind在这里帮不了什么忙,因为它会分割数组元素 我发现的解决方案是将数组元素设置为键:值对,并成功地扩展
> db.final.aggregate([
... {"$project" : {"pro" : { "$setDifference" :[{"$map" : {"input" : "$props","as" : "array_elem", "in" : { "$cond" : [ { "$eq" : [ "$$array_elem.n", "pro" ] }, "$$array_elem.v", null]}}}, [null] ] },props:1}},
... {"$project" : {"loc" : { "$setDifference" :[{"$map" : {"input" : "$props","as" : "array_elem", "in" : { "$cond" : [ { "$eq" : [ "$$array_elem.n", "loc" ] }, "$$array_elem.v", null]}}}, [null] ] },props:1,pro:1}},
... {"$project" : {"port" : { "$setDifference" :[{"$map" : {"input" : "$props","as" : "array_elem", "in" : { "$cond" : [ { "$eq" : [ "$$array_elem.n", "port" ] }, "$$array_elem.v", null]}}}, [null] ] },props:1,pro:1,loc:1}},
... {"$project" : {"ip" : { "$setDifference" :[{"$map" : {"input" : "$props","as" : "array_elem", "in" : { "$cond" : [ { "$eq" : [ "$$array_elem.n", "ip" ] }, "$$array_elem.v", null]}}}, [null] ] },props:1,pro:1,loc:1,port:1}},
... {"$project" : {"ip_addr" : { "$setDifference" :[{"$map" : {"input" : "$props","as" : "array_elem", "in" : { "$cond" : [ { "$eq" : [ "$$array_elem.n", "ip_addr" ] }, "$$array_elem.v", null]}}}, [null] ] },props:1,pro:1,loc:1,port:1,ip:1}},
... {"$project" : {"ipaddr" : { "$setDifference" :[{"$map" : {"input" : "$props","as" : "array_elem", "in" : { "$cond" : [ { "$eq" : [ "$$array_elem.n", "ipaddr" ] }, "$$array_elem.v", null]}}}, [null] ] },pro:1,loc:1,port:1,ip:1,ip_addr:1}}
... ])
//Result(I have used data given in your question):
{ "_id" : 2, "pro" : [ "tcp" ], "loc" : [ "NW" ], "port" : [ "13438" ], "ip" : [ "1.1.1.1" ], "ip_addr" : [ ], "ipaddr" : [ ] }
{ "_id" : 5, "pro" : [ "tcp" ], "loc" : [ "NW" ], "port" : [ "53" ], "ip" : [ "1.1.1.1" ], "ip_addr" : [ ], "ipaddr" : [ ] }
{ "_id" : 1, "pro" : [ "udp" ], "loc" : [ "NW" ], "port" : [ "53" ], "ip" : [ ], "ip_addr" : [ "2.2.2.2" ], "ipaddr" : [ ] }
{ "_id" : 3, "pro" : [ "tcp" ], "loc" : [ "NW" ], "port" : [ "53" ], "ip" : [ ], "ip_addr" : [ ], "ipaddr" : [ "1.1.1.1" ] }
{ "_id" : 4, "pro" : [ "udp" ], "loc" : [ "LA" ], "port" : [ "53" ], "ip" : [ ], "ip_addr" : [ ], "ipaddr" : [ "1.1.1.1" ] }
{ "_id" : 6, "pro" : [ "udp" ], "loc" : [ "LA" ], "port" : [ "53" ], "ip" : [ "1.1.1.1" ], "ip_addr" : [ ], "ipaddr" : [ ] }
在这里,数组中的每个元素都是键和值。您可以在此文档上应用条件并获得所需的结果。我不会在这里给出完整的答案,因为您已经做了部分
注:
> db.final.aggregate([
... {"$project" : {"pro" : { "$setDifference" :[{"$map" : {"input" : "$props","as" : "array_elem", "in" : { "$cond" : [ { "$eq" : [ "$$array_elem.n", "pro" ] }, "$$array_elem.v", null]}}}, [null] ] },props:1}},
... {"$project" : {"loc" : { "$setDifference" :[{"$map" : {"input" : "$props","as" : "array_elem", "in" : { "$cond" : [ { "$eq" : [ "$$array_elem.n", "loc" ] }, "$$array_elem.v", null]}}}, [null] ] },props:1,pro:1}},
... {"$project" : {"port" : { "$setDifference" :[{"$map" : {"input" : "$props","as" : "array_elem", "in" : { "$cond" : [ { "$eq" : [ "$$array_elem.n", "port" ] }, "$$array_elem.v", null]}}}, [null] ] },props:1,pro:1,loc:1}},
... {"$project" : {"ip" : { "$setDifference" :[{"$map" : {"input" : "$props","as" : "array_elem", "in" : { "$cond" : [ { "$eq" : [ "$$array_elem.n", "ip" ] }, "$$array_elem.v", null]}}}, [null] ] },props:1,pro:1,loc:1,port:1}},
... {"$project" : {"ip_addr" : { "$setDifference" :[{"$map" : {"input" : "$props","as" : "array_elem", "in" : { "$cond" : [ { "$eq" : [ "$$array_elem.n", "ip_addr" ] }, "$$array_elem.v", null]}}}, [null] ] },props:1,pro:1,loc:1,port:1,ip:1}},
... {"$project" : {"ipaddr" : { "$setDifference" :[{"$map" : {"input" : "$props","as" : "array_elem", "in" : { "$cond" : [ { "$eq" : [ "$$array_elem.n", "ipaddr" ] }, "$$array_elem.v", null]}}}, [null] ] },pro:1,loc:1,port:1,ip:1,ip_addr:1}}
... ])
//Result(I have used data given in your question):
{ "_id" : 2, "pro" : [ "tcp" ], "loc" : [ "NW" ], "port" : [ "13438" ], "ip" : [ "1.1.1.1" ], "ip_addr" : [ ], "ipaddr" : [ ] }
{ "_id" : 5, "pro" : [ "tcp" ], "loc" : [ "NW" ], "port" : [ "53" ], "ip" : [ "1.1.1.1" ], "ip_addr" : [ ], "ipaddr" : [ ] }
{ "_id" : 1, "pro" : [ "udp" ], "loc" : [ "NW" ], "port" : [ "53" ], "ip" : [ ], "ip_addr" : [ "2.2.2.2" ], "ipaddr" : [ ] }
{ "_id" : 3, "pro" : [ "tcp" ], "loc" : [ "NW" ], "port" : [ "53" ], "ip" : [ ], "ip_addr" : [ ], "ipaddr" : [ "1.1.1.1" ] }
{ "_id" : 4, "pro" : [ "udp" ], "loc" : [ "LA" ], "port" : [ "53" ], "ip" : [ ], "ip_addr" : [ ], "ipaddr" : [ "1.1.1.1" ] }
{ "_id" : 6, "pro" : [ "udp" ], "loc" : [ "LA" ], "port" : [ "53" ], "ip" : [ "1.1.1.1" ], "ip_addr" : [ ], "ipaddr" : [ ] }