这是文件的结构。
{
"_id" : ObjectId("5548b2b79b9567341c77d352"),
"messages" : [
{
"subject" : "fresh subject ",
"from" : ObjectId("5534b2992a104ed914435c31"),
"_id" : ObjectId("5548b5dab9279faf1c1b8688"),
"created" : ISODate("2015-05-05T12:21:46.261Z"),
"read" : true,
"message" : "fresh message ",
"participants" : [
ObjectId("5534b2992a104ed914435c31"), //logged in user
ObjectId("5530af38576214dd3553331c")
]
},
{
"subject" : " subjet",
"from" : ObjectId("5530af38576214dd3553331c"),
"_id" : ObjectId("5548b608b9279faf1c1b8689"),
"created" : ISODate("2015-05-05T12:22:32.809Z"),
"read" : true,
"message" : "is fresh?",
"participants" : [
ObjectId("5530af38576214dd3553331c")
]
}
],
"participants" : [
ObjectId("5534b2992a104ed914435c31"),
ObjectId("5530af38576214dd3553331c")
],
"__v" : 2
}
在一个特定对象的messages数组中有几个对象。我想只有当该对象的参与者数组包含登录用户时才能获取messages数组中的对象。
我有文档的对象ID(5548b2b79b9567341c77d352),我有登录用户ID(5534b2992a104ed914435c31)。 如何在猫鼬中做同样的事情?
答案 0 :(得分:2)
您可以使用MongoDB的 aggregation framework 来获得所需的结果。聚合管道将包含一个初始步骤,该步骤具有$match
运算符,该运算符根据上述标准过滤文档。下一个管道阶段是$unwind
运算符,它从输入文档中解构消息数组,以便为每个元素输出文档。然后,另一个$match
过滤器仅返回具有参与者ID的文档。然后,$project
运算符的最后一步将只带有指定字段的文档传递给结果:
db.collection.aggregate([
{
"$match": {
"_id" : ObjectId("5548b2b79b9567341c77d352"),
"messages.participants": ObjectId("5534b2992a104ed914435c31")
}
},
{
"$unwind": "$messages"
},
{
"$match": {
"messages.participants": ObjectId("5534b2992a104ed914435c31")
}
},
{
"$project": {
"_id": 0,
"messages": 1
}
}
])
<强>结果强>:
/* 0 */
{
"result" : [
{
"messages" : {
"subject" : "fresh subject ",
"from" : ObjectId("5534b2992a104ed914435c31"),
"_id" : ObjectId("5548b5dab9279faf1c1b8688"),
"created" : ISODate("2015-05-05T12:21:46.261Z"),
"read" : true,
"message" : "fresh message ",
"participants" : [
ObjectId("5534b2992a104ed914435c31"),
ObjectId("5530af38576214dd3553331c")
]
}
}
],
"ok" : 1
}
在Mongoose中,您可以使用相同的 aggregation 管道,如下所示:
// Using the pipeline builder
Model.aggregate({
"$match: {
""_id" : ObjectId("5548b2b79b9567341c77d352"),
"messages.participants": ObjectId("5534b2992a104ed914435c31")
}
})
.unwind("messages")
.match({ "messages.participants": ObjectId("5534b2992a104ed914435c31") })
.project({
"_id": 0,
"messages": 1
})
.exec(function (err, res) {
if (err) return handleError(err);
console.log(res);
});
// Or the simple aggregate method
var pipeline = [
{
"$match": {
"_id" : ObjectId("5548b2b79b9567341c77d352"),
"messages.participants": ObjectId("5534b2992a104ed914435c31")
}
},
{
"$unwind": "$messages"
},
{
"$match": {
"messages.participants": ObjectId("5534b2992a104ed914435c31")
}
},
{
"$project": {
"_id": 0,
"messages": 1
}
}
]
Model.aggregate(pipeline, function (err, res) {
if (err) return handleError(err);
console.log(res);
});
答案 1 :(得分:1)
除了聚合框架之外的另一个解决方案是使用$elemMatch投影运算符。
例如:
var id = '5548b2b79b9567341c77d352';
var loggedInUserId = '5534b2992a104ed914435c31';
var projection = {
participants: 1,
messages: {
$elemMatch: { participants: new ObjectId(loggedInUserId) }
}
};
Model.findById(id, projection, function(err, result) {
console.log(result);
});
这将输出:
{ _id: 5548b2b79b9567341c77d352,
participants: [ 5534b2992a104ed914435c31, 5530af38576214dd3553331c ],
messages:
[ { participants: [Object],
message: 'fresh message ',
read: true,
created: Tue May 05 2015 09:21:46 GMT-0300 (BRT),
_id: 5548b5dab9279faf1c1b8688,
from: 5534b2992a104ed914435c31,
subject: 'fresh subject ' } ] }
答案 2 :(得分:0)
您可以使用Aggregation Framework到$unwind
子文档数组(将它们拆分为您可以匹配的自己的文档。我将使用的查询:
.aggregate([
{$unwind: "$messages"},
{$match:
{"messages.participants": ObjectId("5534b2992a104ed914435c31")}
}
])
这将在与该参与者匹配的每个message
子文档的结果集中返回单独的message
文档。
使用Mongoose构造,这看起来像:
Conversation
.aggregate({$unwind: "messages"})
.match({
"messages.participants": mongoose.Types.ObjectId("5534b2992a104ed914435c31")
})
.exec(cb);
第一个$match
并非绝对必要,但