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中执行相同的操作?