是否可以在具有$ elemMatch投影的同一集合上使用查询投影?

时间:2014-05-16 02:54:11

标签: javascript node.js mongodb mongoose aggregation-framework

据我所知,您可以使用$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'
  ]
}

1 个答案:

答案 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()中投影无法完成的事情。