#javascript #node.js #mongodb #mongoose #aggregation-framework
#javascript #node.js #mongodb #mongoose #агрегация-фреймворк
Вопрос:
Я пытаюсь заполнить после агрегирования и подсчета.
Это мои модели:
Журнал пользователя
const UserLog = new Schema(
{
title: {
type: String,
required: true,
trim: true,
},
article: {
type: mongoose.Schema.ObjectId,
ref: 'Article',
required: true,
},
user: {
type: mongoose.Schema.ObjectId,
ref: 'User',
required: true,
},
},
{ timestamps: true, toJSON: { virtuals: true }, toObject: { virtuals: true } }
);
Статья
const Article = new Schema(
{
title: {
type: String,
required: true,
trim: true,
},
content: {
type: String,
required: true,
},
},
{ timestamps: true, toJSON: { virtuals: true }, toObject: { virtuals: true } }
);
И я выполняю запрос, подобный этому:
export const getCountByArticle = async () => {
const articles = await UserLog.aggregate([
{
$group: { _id: '$article', count: { $sum: 1 } },
},
]);
return articles;
};
Запрос возвращает следующее:
[
{
"_id": "5fcbc12dd895b528289723e6",
"count": 1
},
{
"_id": "5fccefc375c47a3fd49c083d",
"count": 2
}
],
Проблема в том, что я хочу «заполнить» поле _id фактической статьей. Я пробовал $lookup, но это возвращает массив со всеми статьями, а я этого не хочу. Расслабиться у меня тоже не получается. Under — это то, каким я на самом деле хочу видеть результат.
[
{
"_id": "5fcbc12dd895b528289723e6",
"title": "Title",
"content": "contentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontent",
"count": 1
},
{
"_id": "5fccefc375c47a3fd49c083d",
"title": "Title",
"content": "contentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontentcontent",
"count": 2
}
],
Я очень надеюсь, что кто-нибудь сможет мне в этом помочь. Заранее благодарю.
Ответ №1:
Вы можете добавить $lookup
шаг конвейера после $group
этапа в вашей агрегированной операции, который выполняет аналогичную работу с заполнением и изменением формы вашего потока документов Mongoose, используя $mergeObjects
в $replaceRoot
для объединения объединенных документов из массива $group и $lookup:
export const getCountByArticle = async () => {
const articles = await UserLog.aggregate([
{ $group: {
_id: '$article', count: { $sum: 1 }
} },
{ $lookup: {
from: 'articles',
localField: '_id',
foreignField: '_id',
as: 'articles'
} },
{ $replaceRoot: {
newRoot: {
$mergeObjects: [
{ $arrayElemAt: [ '$articles', 0 ] },
'$ROOT'
]
}
} },
{ $project: { articles: 0 } }
]).exec();
return articles;
};
Ответ №2:
Использовать $lookup
для MongoDB> 3.2
{
"$lookup" : {
from: "name of lookup collection",
localField: "field in the input collection",
foreignField: "field in the lookup collection",
as: "field name for the output documents"
}
}