假设我的结构为;
{
"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
list
项id
包含在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."
我错过了什么?
答案 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"
}
]
}