据我所知,您可以使用$elemMatch作为投影来限制子集合数组中的项目。如果使用它,它将返回匹配的子文档的所有字段,无论是否还指定了query projections。
是否可以限制匹配的子文档中返回的字段?你会怎么做?
使用版本3.8.9。
给出简单的模式:
var CommentSchema = mongoose.Schema({
body: String,
created: {
by: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
}
}
});
var BlogSchema = mongoose.Schema({
title: String,
blog: String,
created: {
by: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
}
},
comments: [CommentSchema]
});
var Blog = mongoose.model('Blog',modelSchema);
示例
Blog.findOne({_id: id}, {_id: 1, comments: {$elemMatch: {'created.by': 'Jane'}, body: 1}}, function(err, blog) {
console.log(blog.toJSON());
});
// outputs:
{
_id: 532cb63e25e4ad524ba17102,
comments: [
_id: 53757456d9c99f00009cdb5b,
body: 'My awesome comment',
created: { by: 'Jane', date: Fri Mar 21 2014 20:34:45 GMT-0400 (EDT) }
]
}
// DESIRED OUTPUT
{
_id: 532cb63e25e4ad524ba17102,
comments: [
body: 'My awesome comment'
]
}
答案 0 :(得分:1)
是的,有两种方法可以做到这一点。所以你可以像现在一样使用投影面上的$elemMatch
,稍作修改:
Model.findById(id,
{ "comments": { "$elemMatch": {"created.by": "Jane" } } },
function(err,doc) {
或者只是添加到查询部分并使用位置$
运算符:
Model.findOne(
{ "_id": id, "comments.created.by": "Jane" },
{ "comments.$": 1 },
function(err,doc) {
无论哪种方式都完全有效。
如果您想要更多涉及的内容,可以使用.aggregate()
方法及其$project
运算符代替:
Model.aggregate([
// Still match the document
{ "$match": "_id": id, "comments.created.by": "Jane" },
// Unwind the array
{ "$unwind": "$comments" },
// Only match elements, there can be more than 1
{ "$match": "_id": id, "comments.created.by": "Jane" },
// Project only what you want
{ "$project": {
"comments": {
"body": "$comments.body",
"by": "$comments.created.by"
}
}},
// Group back each document with the array if you want to
{ "$group": {
"_id": "$_id",
"comments": { "$push": "$comments" }
}}
],
function(err,result) {
因此聚合框架不仅可以用于简单地聚合结果。它的$project
运算符为您提供了比.find()
投影更灵活的灵活性。它还允许您过滤和返回多个数组结果,这也是.find()
中投影无法完成的事情。