MongoDB 来自多个模型/模式的查询和一个字段中的 return
MongoDB Query from multiple models / schemas and return in one field
我正在使用 Nodejs 和 MongoDB、mongoose 和 expressjs,创建了一个 Blog API 有用户、文章、喜欢和评论模式。以下是我使用的模式。
const UsersSchema = new mongoose.Schema({
username: { type: String },
email: { type: String },
date_created: { type: Date },
last_modified: { type: Date }
});
const ArticleSchema = new mongoose.Schema({
id: { type: String, required: true },
text: { type: String, required: true },
posted_by: { type: Schema.Types.ObjectId, ref: 'User', required: true },
images: [{ type: String }],
date_created: { type: Date },
last_modified: { type: Date }
});
const CommentSchema = new mongoose.Schema({
id: { type: String, required: true },
commented_by: { type: Schema.Types.ObjectId, ref: 'User', required: true },
article: { type: Schema.Types.ObjectId, ref: 'Article' },
text: { type: String, required: true },
date_created: { type: Date },
last_modified: { type: Date }
});
我真正需要的是当我*获取文章集合时*我还想获取每篇文章的评论数。如何查询mongo?
由于需要查询多个集合,可以使用MongoDB的聚合。
此处:https://docs.mongodb.com/manual/aggregation/
示例:
Article
.aggregate(
{
$lookup: {
from: '<your comments collection name',
localField: '_id',
foreignField: 'article',
as: 'comments'
}
},
{
$project: {
comments: '$comments.commented_by',
text: 1,
posted_by: 1,
images: 1,
date_created: 1,
last_modified: 1
}
},
{
$project: {
hasCommented: {
$cond: {
if: { $in: [ '$comments', '<user object id>' ] },
then: true,
else: false
}
},
commentsCount: { $size: '$comments' },
text: 1,
posted_by: 1,
images: 1,
date_created: 1,
last_modified: 1
}
}
)
聚合有点大,但让我试着解释一下:
首先我们需要过滤$lookup
之后的评论。所以我们 $unwind
他们,让每篇文章只包含一个评论对象,所以我们可以使用 $match
进行过滤(这是过滤阶段,它的工作方式与 <Model>.find()
相同。过滤所需的用户后评论,我们再次 $group
一切,每个评论 $sum: 1
,使用 grouper _id,文章的 _id。我们得到 $first
结果 $text, $images
等等。稍后,我们 $project
一切,但现在我们添加 hasCommented
和 $cond
,简单地做:如果 $comments
大于 0(用户有评论,所以这将是true
,否则,false
。
MongoDB 的聚合框架非常棒,您几乎可以使用它对数据做任何您想做的事情。但请注意,有些东西可能比其他东西贵,请务必阅读参考资料。
我正在使用 Nodejs 和 MongoDB、mongoose 和 expressjs,创建了一个 Blog API 有用户、文章、喜欢和评论模式。以下是我使用的模式。
const UsersSchema = new mongoose.Schema({
username: { type: String },
email: { type: String },
date_created: { type: Date },
last_modified: { type: Date }
});
const ArticleSchema = new mongoose.Schema({
id: { type: String, required: true },
text: { type: String, required: true },
posted_by: { type: Schema.Types.ObjectId, ref: 'User', required: true },
images: [{ type: String }],
date_created: { type: Date },
last_modified: { type: Date }
});
const CommentSchema = new mongoose.Schema({
id: { type: String, required: true },
commented_by: { type: Schema.Types.ObjectId, ref: 'User', required: true },
article: { type: Schema.Types.ObjectId, ref: 'Article' },
text: { type: String, required: true },
date_created: { type: Date },
last_modified: { type: Date }
});
我真正需要的是当我*获取文章集合时*我还想获取每篇文章的评论数。如何查询mongo?
由于需要查询多个集合,可以使用MongoDB的聚合。
此处:https://docs.mongodb.com/manual/aggregation/
示例:
Article
.aggregate(
{
$lookup: {
from: '<your comments collection name',
localField: '_id',
foreignField: 'article',
as: 'comments'
}
},
{
$project: {
comments: '$comments.commented_by',
text: 1,
posted_by: 1,
images: 1,
date_created: 1,
last_modified: 1
}
},
{
$project: {
hasCommented: {
$cond: {
if: { $in: [ '$comments', '<user object id>' ] },
then: true,
else: false
}
},
commentsCount: { $size: '$comments' },
text: 1,
posted_by: 1,
images: 1,
date_created: 1,
last_modified: 1
}
}
)
聚合有点大,但让我试着解释一下:
首先我们需要过滤$lookup
之后的评论。所以我们 $unwind
他们,让每篇文章只包含一个评论对象,所以我们可以使用 $match
进行过滤(这是过滤阶段,它的工作方式与 <Model>.find()
相同。过滤所需的用户后评论,我们再次 $group
一切,每个评论 $sum: 1
,使用 grouper _id,文章的 _id。我们得到 $first
结果 $text, $images
等等。稍后,我们 $project
一切,但现在我们添加 hasCommented
和 $cond
,简单地做:如果 $comments
大于 0(用户有评论,所以这将是true
,否则,false
。
MongoDB 的聚合框架非常棒,您几乎可以使用它对数据做任何您想做的事情。但请注意,有些东西可能比其他东西贵,请务必阅读参考资料。