计算每个文档的子文档

时间:2015-07-24 19:17:55

标签: mongodb mongodb-query

我试图在Mongo中为每个文档计算子文档。

使用db.users.find().length()在集合中轻松获取文档很容易。我想做类似db.users.projects.find().length()的类似事情。我怎么能这样做?

编辑:

我想要的结果是知道每个用户有多少个项目...所以类似:

{_id: 123, projects: 4}

示例用户文档:

{
   _id:{$oid: 123},
   username: johnsmith,
   projects: [{$oid: 456}, {$oid: 789}]
}

4 个答案:

答案 0 :(得分:4)

Per @ n9code,您将需要聚合框架。但是,您可以使用$size非常轻松地计算子文档:

db.users.aggregate([{
  $project: {
    _id: '$_id',
    totalProjects: { $size: "$projects" }
  }
}]);

哪个应该返回这样的内容:

{ "_id" : ObjectID(...), "totalProjects" : 89 }, ...

$size将返回每个文档的projects数组的长度,并$project更改文档的格式以包含totalProjects作为{{1}的大小数组。

答案 1 :(得分:0)

您需要MongoDB的Aggregation Framework

db.users.aggregate({$unwind: '$projects'}).count()

这将展开集合中每个文档中的projects数组字段,这将是projects子文档的总数。

答案 2 :(得分:0)

您的设计中似乎可能有多个用户名文档,例如

{ username: "buzz", projects: [ list of 2 things ] }
{ username: "dan". projects: [ list of 3 things ] }
{ username: "buzz", projects: [ list of 4 things ] }

要获得每个username项目的“赠款总额”,请尝试以下方法:

c = db.foo.aggregate([
{$project: {
    "username": 1,
    "n": {$size: "$projects"}
}
}
, 
{$group: {
    "_id": "$username",
    "alln": {$sum: "$n"}
}
}
]);

产生

{ "_id" : "buzz", "alln" : 6 }
{ "_id" : "dan", "alln" : 3 }

答案 3 :(得分:0)

使用VirtualType()使用mongoose计数子文档的更好方法 让我们通过一个使用Blogpost和Comment模式设计的简单示例来了解这一点

const Blogpost = new Schema({
    title: { type: String, required: true },
    body: { type: String, required: true },
    userId: { type: Schema.Types.ObjectId, ref: 'User', required: true },
    commentId: [{ type: Schema.Types.ObjectId, ref: 'Comment' }],
    lastModifiedAt: { type: Date, default: Date.now },
    createdAt: { type: Date, default: Date.now },
})


const Comment = new Schema({
    postId: { type: Schema.Types.ObjectId, ref: 'Post', required: true },
    userId: { type: Schema.Types.ObjectId, ref: 'User', required: true },
    text: { type: String, required: true },
    lastModified: { type: Date, default: Date.now },
    createdAt: { type: Date, default: Date.now }
})

现在,如果我们必须获取每篇博客文章的totalComments,那么我们必须在Blogpost架构设计中创建一个VirtualType

Blogpost.virtual('totalComments', {
    ref: 'Comment', // model to use for matching
    localField: '_id', // from `localField` i.e., Blogpost
    foreignField: 'postId', // is equal to `foreignField` of Comment schema
    count: true //only get the number of docs
});

Blogpost.set('toObject', { virtuals: true });
Blogpost.set('toJSON', { virtuals: true });

由于我们在Comment模式中具有postId,该id包含与该特定Blogpost关联的Blogpost._id,因此只有我们能够匹配并获取每个Blogpost的totalComments

现在使用人口,我们可以获得每个Blogpost的totalComments

let blogpost = await Blogpost.model
    .find({})
    .populate({ path: 'totalComments', count: true })