可以使用聚合框架由给定组ID和成员阵列状态字段来筛选组收集的文件。这将是您的初始管道阶段,这是运营商驱动的$match
。
下一个流水线步骤应该是$filter
运算符,它根据给定的条件选择成员数组的子集。这是必要的,因为前一个流水线只能在文档级进行过滤,而不能在数组/字段级进行过滤。
一旦你得到了过滤的数组,你可以应用功能作为“填充”你的成员名单的手段。然而,由于localField
是一个数组,要匹配它里面的元素反对foreignField
这是一个单一的元素,你需要$unwind
数组作为聚合管线的一个阶段应用$lookup
运营商之前。
下面的例子演示了如何应用在你的情况下,所有上述步骤:
Group.aggregate([
{
"$match": {
"_id": groupId,
"members.status": 1
}
},
{
"$filter": {
"input": "$members",
"as": "member",
"cond": { "$eq": ["$$member.status", 1] }
}
}
{ "$unwind": "$members" },
{
"$lookup": {
"from": "users"
"localField": "members.user_id",
"foreignField": "_id",
"as": "member"
}
}
]).exec(function(err, results) {
if (err) throw err;
console.log(results);
});
结果将包含具有两个组和用户属性的文件清单。
如果您的MongoDB的版本不支持在3.2版本中引入的$filter
和$lookup
运营商。X和更新,然后考虑使用$setDifference
和$map
操作者的组合来过滤在$project
管线数组元素。
的$map
操作在本质上创建保持值作为一个子表达式到数组的每个元素的逻辑评价的结果的新的数组字段。然后,运算符返回一个集合,其中的元素出现在第一个集合中,但不出现在第二个集合中;即执行第二组相对于第一组的相对补偿。在这种情况下,它将通过status
属性返回包含与父文档无关的元素的最终成员数组。
的$project
流水线工序后,执行总运行和自恢复的文件都是普通的JavaScript对象,而不是Mongoose Documents(可以返回文档的任何形状),你需要转换的结果,Mongoose Documents这样就可以使用用结果在现场填充函数。
下面的例子演示了上述解决办法:
Group.aggregate([
{
"$match": {
"_id": groupId,
"members.status": 1
}
},
{
"$project": {
"type": 1, "name": 1,
"members": {
"$setDifference": [
{
"$map": {
"input": "$members",
"as": "member",
"in": {
"$cond": [
{ "$eq": [ "$$member.status", 1 ] },
"$$member",
false
]
}
}
},
[false]
]
}
}
}
]).exec(function(err, result) {
if (err) throw err;
var docs = result.map(function(doc) { return new Group(doc) });
Group.populate(docs, { "path": "members" }, function(err, results) {
if (err) throw err;
console.log(JSON.stringify(results, undefined, 4));
res.json(results);
});
});
您的意思是对于给定的,而不是_group_对象_post_对象? – chridam
除了给出Schema定义之外,分享少量示例文档和预期输出将会很好,这样很容易理解您要完成的任务。 – superUser
@chridam'组'对象。编辑了这个问题。 –