Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mongodb 聚合以获取数组中键值对的总数,并根据类似名称的字段值进行分组_Mongodb_Mongodb Query_Aggregation Framework - Fatal编程技术网

Mongodb 聚合以获取数组中键值对的总数,并根据类似名称的字段值进行分组

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

我有如下结构的文档,其中每个数组元素都包含“n”和“v”作为不同类型数据的键和值。我需要按“ipaddress”的“n”值对其进行分组,并计算集合中的全部不同组合。但是,值相似但不相同。(例如:ip、ip地址和ip地址)

查询选择条件如下:

  • 如果“loc”为“NW”且“logtype”为“1”,则“ipaddress”=“ip”
  • 如果“loc”为“NW”且“logtype”为“2”,则“ipaddress”=“ip地址”
  • 如果“loc”为“NW”且“logtype”为“3”,则“ipaddress”=“ipaddress”
  • 港口是“53”
  • pro是“udp”或“tcp”
  • 按“IP地址”分组
  • 我想要这样的结果

    {"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" : [ ] }
    
    在这里,数组中的每个元素都是键和值。您可以在此文档上应用条件并获得所需的结果。我不会在这里给出完整的答案,因为您已经做了部分

    注:

  • MongoDB不允许在aggregation()中使用$elemMatch,而用于此的解决方法是增加聚合管道的大小
  • 若数组中元素的位置是可靠的,那个么可以简单地将数组元素转换为键:值对
  • > 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" : [ ] }