$ project和$ in in mongodb查询

时间:2017-03-21 06:55:00

标签: mongodb mongodb-query aggregation-framework

假设我的结构为;

{
    "class" : "TESTCLASS",
    "id" : "HyvF1sdZl",
    "depends" : [
        "S11T5ce",
        "BytQLN6ml",
        "Byzz8Ea7l",
        "r1TUNX58x"
    ],
    "list" : [
        {
            "class" : "DATA",
            "id" : "H113d5Pwx"
        },
        {
            "class" : "DATA",
            "id" : "H113d5Pwx"
        },
        {
            "class" : "TEST",
            "id" : "r1TUNX58x"
        },
        {
            "class" : "DATA",
            "id" : "H113d5Pwx"
        },
        {
            "class" : "TEST",
            "id" : "r1TUNX58x"
        },
        {
            "class" : "TEST",
            "id" : "r1TUNX58x"
        },
        {
            "class" : "FDSAFAS",
            "id" : "S11T5ce"
        },
        {
            "class" : "YENITEST",
            "id" : "r1TUNX58x"
        },
        {
            "class" : "FDSAFAS",
            "id" : "S11T5ce"
        },
        {
            "class" : "CALENDAR",
            "id" : "S11T5ce"
        },
        {
            "class" : "EN",
            "id" : "BytQLN6ml"
        },
        {
            "class" : "CALENDAR",
            "id" : "S11T5ce"
        },
        {
            "class" : "EN_",
            "id" : "Byzz8Ea7l"
        },
        {
            "class" : "TEST",
            "id" : "r1TUNX58x"
        },
        {
            "class" : "EN",
            "id" : "BytQLN6ml"
        },
        {
            "class" : "FDSAFAS",
            "id" : "S11T5ce"
        }
    ]
}

我想project listid包含在depends数组中。{/ p>

我的意思是,我只想得到;

"depends" : [
   "S11T5ce",
   "BytQLN6ml",
   "Byzz8Ea7l",
   "r1TUNX58x"
],
"list" : [
    {
        "class" : "FDSAFAS",
        "id" : "S11T5ce"
    },
    {
        "class" : "EN",
        "id" : "BytQLN6ml"
    },
    {
        "class" : "EN_",
        "id" : "Byzz8Ea7l"
    },
    {
        "class" : "TEST",
        "id" : "r1TUNX58x"
    }

]

为了能够做到这一点,我写了;

db.definition.aggregate([
    {
        $project: {
            _id: 0,
            depends :1,
            depends: {$in: ["$list.id"]},
            "list.defid": 1,
            "list.class" :1,
        }

    }
]).pretty() 

但这会引发错误"errmsg" : "Expression $in takes exactly 2 arguments. 1 were passed in."

我错过了什么?

2 个答案:

答案 0 :(得分:1)

您可以先使用$project$filter过滤掉id不在depends数组中的对象,然后按ID返回唯一对象,并且包含类有点问题因为如果您使用$addToSet,则无法指定要使其唯一的字段但忽略对象中的其他字段,或者在此情况下忽略列表中的class

db.col.aggregate([
    {$project: {
        depends: 1,
        class: 1,
        list: {
            $filter: {
                input: '$list',
                as: 'item',
                cond: {
                    $setIsSubset: [['$$item.id'], '$depends']
                }
            }
        }
    }},
    {$unwind: '$list'},
    {$group: {
        _id: '$_id',
        depends: {$first: '$depends'},
        class: {$first: '$class'},
        list: {
            $addToSet: {
                id: '$list.id',
                class: '$list.class'
            }
        },

    }}
])

最终结果是

[{
  "_id": "58d0cea6aecf3102684e4f0e",
  "depends": ["S11T5ce", "BytQLN6ml", "Byzz8Ea7l", "r1TUNX58x"],
  "class": "TESTCLASS",
  "list": [{
    "id": "Byzz8Ea7l",
    "class": "EN_"
  }, {
    "id": "BytQLN6ml",
    "class": "EN"
  }, {
    "id": "S11T5ce",
    "class": "FDSAFAS"
  }, {
    "id": "r1TUNX58x",
    "class": "YENITEST"
  }, {
    "id": "S11T5ce",
    "class": "CALENDAR"
  }, {
    "id": "r1TUNX58x",
    "class": "TEST"
  }]
}]

答案 1 :(得分:1)

使用MongoDB 3.4,您可以使用 $addFields 管道来投影其他字段,而无需明确命名它们。作为单个管道,使用 $setUnion $filter $in 运算符的组合返回所需的 阵列。在应用 $setUnion 运算符之前, $filter 运算符有助于消除重复项。

为了遵循直觉,让我们按照与 $filter 运算符一起运行的示例管道进行操作:

db.collection.aggregate([
    {
        "$addFields": {
            "list": {
                "$filter": {
                    "input": "$list",
                    "as": "item",
                    "cond": { "$in": ["$$item.id", "$depends"] }                       
                }
            }
        }
    }
])

示例输出

{
    "_id" : ObjectId("58d0e0d97a3871921504bb69"),
    "class" : "TESTCLASS",
    "id" : "HyvF1sdZl",
    "depends" : [
        "S11T5ce",
        "BytQLN6ml",
        "Byzz8Ea7l",
        "r1TUNX58x"
    ],  
    "list" : [ 
        {
            "class" : "TEST",
            "id" : "r1TUNX58x"
        }, 
        {
            "class" : "TEST",
            "id" : "r1TUNX58x"
        }, 
        {
            "class" : "TEST",
            "id" : "r1TUNX58x"
        }, 
        {
            "class" : "FDSAFAS",
            "id" : "S11T5ce"
        }, 
        {
            "class" : "YENITEST",
            "id" : "r1TUNX58x"
        }, 
        {
            "class" : "FDSAFAS",
            "id" : "S11T5ce"
        }, 
        {
            "class" : "CALENDAR",
            "id" : "S11T5ce"
        }, 
        {
            "class" : "EN",
            "id" : "BytQLN6ml"
        }, 
        {
            "class" : "CALENDAR",
            "id" : "S11T5ce"
        }, 
        {
            "class" : "EN_",
            "id" : "Byzz8Ea7l"
        }, 
        {
            "class" : "TEST",
            "id" : "r1TUNX58x"
        }, 
        {
            "class" : "EN",
            "id" : "BytQLN6ml"
        }, 
        {
            "class" : "FDSAFAS",
            "id" : "S11T5ce"
        }
    ]
}

使用 $setUnion 运算符,在应用 $filter 之前首先删除重复项:

db.collection.aggregate([
    {
        "$addFields": { 

            "list": {
                "$filter": {
                    "input": { "$setUnion": ["$list", []] },
                    "as": "item",
                    "cond": { "$in": ["$$item.id", "$depends"] }                       
                }                
            }            
        }
    }
])

示例输出

{
    "class" : "TESTCLASS",
    "id" : "HyvF1sdZl",
    "depends" : [ 
        "S11T5ce", 
        "BytQLN6ml", 
        "Byzz8Ea7l", 
        "r1TUNX58x"
    ],
    "list" : [ 
        {
            "class" : "FDSAFAS",
            "id" : "S11T5ce"
        }, 
        {
            "class" : "TEST",
            "id" : "r1TUNX58x"
        }, 
        {
            "class" : "YENITEST",
            "id" : "r1TUNX58x"
        }, 
        {
            "class" : "EN_",
            "id" : "Byzz8Ea7l"
        }, 
        {
            "class" : "CALENDAR",
            "id" : "S11T5ce"
        }, 
        {
            "class" : "EN",
            "id" : "BytQLN6ml"
        }
    ]
}