MongoDB Запрос из нескольких моделей / схем и возврат в одно поле
Я использую Nodejs и MongoDB, mongoose и expressjs, создаю 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 }
});
Что мне действительно нужно, так это когда я * получаю сборник статей * Я также хочу собрать количество комментариев для каждой статьи. Как я могу запросить монго?
1 ответ
Поскольку вам нужно запросить более одной коллекции, вы можете использовать агрегацию 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
для каждого комментария, используя в качестве группы _id, _id статьи. И мы получаем $first
результат для $text, $images
и т. д. Позже мы $project
все, но теперь мы добавим hasCommented
с $cond
просто делаю: если $comments
больше 0(пользователь прокомментировал, так что это будет true
еще false
,
Платформа агрегации MongoDB - это круто, и вы можете делать с ней практически все, что захотите. Но имейте в виду, что некоторые вещи могут стоить больше, чем другие, всегда читайте ссылку.