Javascript 是否可以在具有$elemMatch投影的同一集合上使用查询投影?
我知道您可以使用作为投影来限制子集合数组中的项。这样使用时,它返回匹配的子文档的所有字段,而不管是否也指定了 是否可以限制匹配子文档中返回的字段?你会怎么做 使用版本3.8.9 给定简单的模式:Javascript 是否可以在具有$elemMatch投影的同一集合上使用查询投影?,javascript,node.js,mongodb,mongoose,aggregation-framework,Javascript,Node.js,Mongodb,Mongoose,Aggregation Framework,我知道您可以使用作为投影来限制子集合数组中的项。这样使用时,它返回匹配的子文档的所有字段,而不管是否也指定了 是否可以限制匹配子文档中返回的字段?你会怎么做 使用版本3.8.9 给定简单的模式: var CommentSchema = mongoose.Schema({ body: String, created: { by: { type: String, required: true }, date: { type: Dat
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'
]
}
是的,有两种方法可以做到这一点。因此,您可以在投影侧使用现有的,只需稍作更改:
Model.findById(id,
{ "comments": { "$elemMatch": {"created.by": "Jane" } } },
function(err,doc) {
或者只需添加到查询部分并使用位置$
运算符:
Model.findOne(
{ "_id": id, "comments.created.by": "Jane" },
{ "comments.$": 1 },
function(err,doc) {
任何一种方法都是完全有效的
如果您想要比这更复杂的内容,可以使用该方法及其运算符:
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) {
因此,聚合框架的用途远不止是简单地聚合结果。与使用
.find()
进行投影相比,它的运算符为您提供了更大的灵活性。它还允许您过滤和返回多个数组结果,这也是在.find()
中使用投影无法完成的。感谢您的快速响应,但我认为我没有充分强调我的问题。我知道如何使用这两种方法过滤注释
子集合,但我还想在同一个子集合上使用查询投影来选择要为每个子文档返回的字段。我已经编辑了我的原始问题,以包含一个更明显的所需输出的示例。@Jason我在这个阶段看不到您的问题中有任何编辑,但我认为根据您的评论,aggregate
示例的一些变体就是您要找的。抱歉。我以为我昨晚保存了更新,但显然没有。所以这只是.find()
和$elemMatch
中的投影限制?我也在研究聚合方法,但担心使用.find()
是否会造成严重的性能损失。我今天去看看。再次感谢。@JasonCust一般的限制是,仅使用.find()
就相当有限,虽然您可以执行类似comments.body
的操作并获取所有数组成员,但仅获取body字段,但您不能执行comments.$.body
仅获取匹配的一个。因此,aggregate
的使用确实会带来一些额外的成本,因为它需要做更多的事情,但是这应该可以忽略不计,除非您的数组非常大。这也是在数组元素中获得1个以上匹配项的唯一方法。