mongodb查询中的$project和$in

mongodb查询中的$project和$in,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,假设我的结构是 { "class" : "TESTCLASS", "id" : "HyvF1sdZl", "depends" : [ "S11T5ce", "BytQLN6ml", "Byzz8Ea7l", "r1TUNX58x" ], "list" : [ { "class" : "DATA", "id" : "H113d5Pw

假设我的结构是

{
    "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"
        }
    ]
}
我想
项目
列表
id
包含在
依赖
数组中的项目

我的意思是,我只想得到

"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”:“表达式$in正好包含2个参数。传入了1个参数。”


我遗漏了什么?

您可以首先使用
$project
$filter
筛选出id不在
依赖的
数组中的对象,然后按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"
  }]
}]

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

为了遵循直觉,让我们遵循这个仅使用操作符运行的示例管道:

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"
        }
    ]
}
{
    "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"
        }
    ]
}
使用操作符,在应用之前,先消除重复项,如下所示:

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

            "list": {
                "$filter": {
                    "input": { "$setUnion": ["$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"
        }
    ]
}
{
    "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"
        }
    ]
}

如果您不想在最终结果中使用id,您可以在MongoDB 3.4的末尾再添加一个
$project
,您应该使用聚合运算符,而不是
$setIsSubset
,我如何在Java API中执行相同的操作?