如何获取 mongoose/mongodb 文档中对象数组中的对象?
How to get the objects inside an array of objects which is inside an document in mongoose/mongodb?
这是文档的结构。
{
"_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
}
特定对象的消息数组中有多个对象。仅当该对象的参与者数组包含登录用户时,我才想获取消息数组中的对象。
我有文档的对象 ID (5548b2b79b9567341c77d352) 和登录用户 ID (5534b2992a104ed914435c31)。
如何在猫鼬中做同样的事情?
您可以使用 MongoDB 的 aggregation framework to get the desired result. The aggregation pipeline would consist of an initial step which has a $match
operator that filters the documents based on the criteria above. The next pipeline stage would be the $unwind
operator that deconstructs the messages array from the input documents to output a document for each element. A further $match
filter then returns only the documents with the participant id. The final step with the $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);
});
您可以使用 Aggregation Framework to $unwind
子文档数组(将它们拆分为您可以匹配的自己的文档。我将使用的查询:
.aggregate([
{$unwind: "$messages"},
{$match:
{"messages.participants": ObjectId("5534b2992a104ed914435c31")}
}
])
这将 return 在结果集中为与该参与者匹配的每个 message
子文档创建一个单独的 message
文档。
使用 Mongoose 构造这看起来像:
Conversation
.aggregate({$unwind: "messages"})
.match({
"messages.participants": mongoose.Types.ObjectId("5534b2992a104ed914435c31")
})
.exec(cb);
第一个 $match
不是绝对必要的,但
除了聚合框架之外的另一种解决方案是使用 $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 ' } ] }
这是文档的结构。
{
"_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
}
特定对象的消息数组中有多个对象。仅当该对象的参与者数组包含登录用户时,我才想获取消息数组中的对象。
我有文档的对象 ID (5548b2b79b9567341c77d352) 和登录用户 ID (5534b2992a104ed914435c31)。 如何在猫鼬中做同样的事情?
您可以使用 MongoDB 的 aggregation framework to get the desired result. The aggregation pipeline would consist of an initial step which has a $match
operator that filters the documents based on the criteria above. The next pipeline stage would be the $unwind
operator that deconstructs the messages array from the input documents to output a document for each element. A further $match
filter then returns only the documents with the participant id. The final step with the $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);
});
您可以使用 Aggregation Framework to $unwind
子文档数组(将它们拆分为您可以匹配的自己的文档。我将使用的查询:
.aggregate([
{$unwind: "$messages"},
{$match:
{"messages.participants": ObjectId("5534b2992a104ed914435c31")}
}
])
这将 return 在结果集中为与该参与者匹配的每个 message
子文档创建一个单独的 message
文档。
使用 Mongoose 构造这看起来像:
Conversation
.aggregate({$unwind: "messages"})
.match({
"messages.participants": mongoose.Types.ObjectId("5534b2992a104ed914435c31")
})
.exec(cb);
第一个 $match
不是绝对必要的,但
除了聚合框架之外的另一种解决方案是使用 $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 ' } ] }