#mongodb #mongodb-query
#mongodb #mongodb-запрос
Вопрос:
Извините, я новичок, я использую поиск с двумя документами, здесь у меня есть 3 таблицы:
const Product = {
id: ObjectId,
name: String
}
const user = {
id: ObjectId,
name: String
}
const comment = {
id: ObjectId,
product: ObjectId('product'),
user: ObjectId('user'),
parentComment: ObjectId('comment')
text: String
}
const rate = {
id: ObjectId,
product: ObjectId('product'),
user: ObjectId('user')
rate: Number
}
Когда пользователь хочет увидеть конкретный продукт, я показываю ему комментарий и оценку продукта, сначала я запрашиваю комментарии, чем запрашиваю пользователя, который опубликовал комментарий, и значение оценки, если они оценили продукт, я реализую поиск следующим образом:
commentModel.aggregate([
{
$match:{
product: mongoose.Types.ObjectId(req.query.productID),
parent: null
},
},
{
$lookup:
{
'from': 'users',
'localField': 'user',
'foreignField': 'id',
'as': 'user'
}
},
{
$lookup:
{
'from': 'rates',
'pipeline': [
{ $match: {product: mongoose.Types.ObjectId(req.query.productID), user: 'user.id'}}
],
'as': 'rateValue'
}
}
])
Первый поиск работает нормально, но скорость не изменилась, он всегда возвращает пустые массивы, кто-нибудь может мне помочь, спасибо
Ответ №1:
Есть несколько исправлений,
- Вам нужно
$unwind
деконструировать пользовательский массив, потому что $lookup не позволит присоединиться к полю массива, - чтобы сопоставить поле родительской коллекции в lookup, вы должны определить переменную с помощью
let
в lookup, - чтобы соответствовать выражению, вам нужно использовать
$expr
commentModel.aggregate([
{
$match: {
product: mongoose.Types.ObjectId(req.query.productID),
parentComment: null
}
},
{
$lookup: {
from: "users",
as: "user",
localField: "user",
foreignField: "id"
}
},
// add this
{ $unwind: "$user" },
{
$lookup: {
from: "rates",
let: { userId: "$user.id" }, // add this
pipeline: [
{
$match: {
product: mongoose.Types.ObjectId(req.query.productID),
$expr: { $eq: ["$user", "$$userId"] }
}
}
],
as: "rateValue"
}
}
])
Другой вариант, без $unwind
Комментарии:
1. Большое вам спасибо за первый, он работает, но второй, можете ли вы объяснить,
let: { userId: "$user" },
,$user
ссылка на какой из них? Пользовательская модель или rateModel? Спасибо2. идентификатор пользователя $ из модели комментариев, потому что, взглянув на свой запрос, вы заменяете пользователя при поиске на user
as: 'user'
но я использовалusers
, и поле user уже есть.
Ответ №2:
Вы также можете попробовать это
[
{
$match:{
product: mongoose.Types.ObjectId(req.query.productID),
parent: null
},
},
{
$lookup: {
'from': 'users',
'localField': 'user',
'foreignField': 'id',
'as': 'user'
}
},
{
$lookup: {
'from': 'rates',
'localField': 'user',
'foreignField': 'user',
'as': 'rateDetail'
}
},
{
$unwind: '$rateDetail'
},
{
$match: {
'$rateDetail.product':mongoose.Types.ObjectId(req.query.productID)
}
}
]
Комментарии:
1. Спасибо вам, я использовал это раньше, но когда я попробую, я обнаружил, что rateDetail попадет в список массива, если пользователь проголосует за множество продуктов, этот массив будет больше, запрос может быть медленным, и со многими пользователями, использующими этот запрос, я боюсь, что это займет много времени