Я пытаюсь найти все отзывы для данного элемента, загруженные пользователем. Я хочу отобразить на странице своего профиля пользователя список всех его загруженных продуктов и для каждого элемента хочу отобразить несколько отзывов. Для этого я пытаюсь сгруппировать все отзывы по пунктам. Сначала я пытаюсь сделать это с агрегацией, чтобы сгруппировать все отзывы по элементам, после этого я хочу заполнить item внутри результата агрегации, чтобы получить некоторые поля, такие как заголовок и рейтинг. Кроме того, я пытаюсь заполнить reviews.user , так как мне нужно получить имя пользователя, написавшего обзор. Это не сложный запрос, однако синтаксис $ lookup мешает мне достичь этого. Заранее всем спасибо за помощь.
У меня есть эти схемы
const reviewSchema = new Schema(
{
text: { type: String, max: [400, 'Too long, max is 400 characters']},
createdAt: { type: Date, default: Date.now },
rating : { type: Number },
user: {type: Schema.Types.ObjectId, ref:'User'},//User who wrote review
item: {type: Schema.Types.ObjectId, ref:'Item', default: null},// Review belongs to this item
});
const userSchema = new Schema(
{
username: { type: String, max: [20, 'Too long, max is 20 characters']},
createdAt: { type: Date, default: Date.now },
rating : { type: Number },
email: { type: Number },
items: [{type: Schema.Types.ObjectId, ref:'Item'}]
// Some more info
});
const itemSchema = new Schema(
{
title: { type: String, max: [40, 'Too long, max is 40 characters']},
rating: { type: number },
user : {type: Schema.Types.ObjectId, ref:'User'},
// Some more info
});
Я дошел до того, что заметил, что мне нужно заполнить массив внутри конвейера агрегации.
const resolvedItemReviews = await Promise.all(user.items.map(async (rental) =>{
return new Promise((resolve, reject) =>
{
Review.aggregate([
{ "$match": {$and: [
{item: item._id},
{_id: { $nin: queryObj.seenIDs }}
]}},
{ '$limit' : 5},
{ "$sort": { "createdAt": 1 } },
{ "$group": {
"_id": "$item",
"item": {'$first': '$item'},
"reviews": { $push: {"text": "$text","user": "$user","rating": "$rating" ,"createdAt": "$createdAt"} },
}
},
// unwind source
{"$unwind": "$reviews"},
{ "$lookup": {
"from": "User",
"localField": "reviews.user",
"foreignField": "_id",
"as": "reviewUser"
}},
{ "$unwind": "$reviewUser" },
],
async function(err,results) {
if (err) reject(err);
console.log(results)
await Item.populate(results, { "path": "rental", select: 'title image rating'})
resolve( results )
})
});
})
В настоящее время я получаю этот результат:
[ { _id: 5c94061acd2e4e50a4e921aa,
item: 5c94061acd2e4e50a4e921aa,
reviews:
{ text:
'Lorem ipsum dolor sit amet',
user: 5c1c774ccc273b1584925b9d,
rating: 5,
createdAt: 2019-03-21T21:49:03.510Z } },
{ _id: 5c94061acd2e4e50a4e921aa,
item: 5c94061acd2e4e50a4e921aa,
reviews:
{ text:
'Lorem ipsum dolor sit amet,',
user: 5c5a3cb031c62708c4143f82,
rating: 5,
createdAt: 2019-03-21T22:10:10.013Z } } ]
И это будет ожидаемый результат
[ { _id: 5c940eb1c1d32b4fdc5c7ef4,
item: {
_id: 5c940eb1c1d32b4fdc5c7ef4
title: "Item title text",
rating: 4.3,
image: "https://www.imageurl.com",
},
reviews:
{ text: 'Some review text',
user: {
username: "TestUser",
rating: 4.6,
image: "https://www.user-imageurl.com",
},
rating: 4,
createdAt: 2019-03-21T22:23:59.105Z }
},
{ text: 'Some review text from another user',
user: {
username: "TestUser 2",
rating: 3.1,
image: "https://www.user2-imageurl.com",
},
rating: 3,
createdAt: 2019-02-21T22:23:59.105Z }
}
]