获取结果作为数组而不是mongodb中的文档作为属性

时间:2014-08-18 16:12:18

标签: node.js mongodb mongoose

我有一个带有架构的用户集合

{
     name: String, 
     books: [
         id: { type: Schema.Types.ObjectId, ref: 'Book' } ,
         name: String
     ]


}

是否可以获取一组图书ID而不是对象?

类似的东西:

["53eb797a63ff0e8229b4aca1", "53eb797a63ff0e8229b4aca2", "53eb797a63ff0e8229b4aca3"]

{ids: ["53eb797a63ff0e8229b4aca1", "53eb797a63ff0e8229b4aca2", "53eb797a63ff0e8229b4aca3"]}

而不是

{
    _id: ObjectId("53eb79d863ff0e8229b97448"),
    books:[
        {"id" : ObjectId("53eb797a63ff0e8229b4aca1") }, 
        { "id" : ObjectId("53eb797a63ff0e8229b4acac") }, 
        { "id" : ObjectId("53eb797a63ff0e8229b4acad") }
    ]
}

目前我在做

User.findOne({}, {"books.id":1} ,function(err, result){
    var bookIds = [];
    result.books.forEach(function(book){
        bookIds.push(book.id);
    });

});

还有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

可以使用Aggregation Pipeline$unwind轻松完成$group

db.users.aggregate({
  $unwind: '$books'
}, {
  $group: {
    _id: 'books',
    ids: { $addToSet: '$books.id' }
  }
})

使用mongoose Model.aggregate() method的相同操作:

User.aggregate().unwind('$books').group(
  _id: 'books',
  ids: { $addToSet: '$books.id' }
}).exec(function(err, res) {
  // use res[0].ids
})

请注意,此处的books不是mongoose文档,而是普通的js对象。


您还可以添加$match以选择用户集合的某些部分来运行此聚合查询。

例如,您可以只选择一个特定用户:

User.aggregate().match({
  _id: uid
}).unwind('$books').group(
  _id: 'books',
  ids: { $addToSet: '$books.id' }
}).exec(function(err, res) {
  // use res[0].ids
})

但如果您对将不同用户的图书汇总到单个数组不感兴趣,最好不要使用$group$unwind来执行此操作:

User.aggregate().match({
  _id: uid
}).project({
  _id: 0,
  ids: '$books.id'
}).exec(function(err, users) {
  // use users[0].ids
})