如何在猫鼬的子文档数组中查找字段?
How to lookup a field in an array of subdocuments in mongoose?
我有一组这样的评论对象:
"reviews": {
"author": "5e9167c5303a530023bcae42",
"rate": 5,
"spoiler": false,
"content": "This is a comment This is a comment This is a comment.",
"createdAt": "2020-04-12T16:08:34.966Z",
"updatedAt": "2020-04-12T16:08:34.966Z"
},
我想要实现的是查找 author 字段并获取用户数据,但问题是我尝试使用的查找仅 returns这对我来说:
代码:
.lookup({
from: 'users',
localField: 'reviews.author',
foreignField: '_id',
as: 'reviews.author',
})
回复:
有什么方法可以获取作者在该领域的数据?那里是作者的id。
你应该在对服务器的请求上使用 mongoose 的 populate('author')
方法,该方法获取该作者的 id 并将用户数据添加到 mongoose 的响应中
并且不要忘记以连接这两个集合的方式设置架构
在您的审核模式中,您应该将 ref 添加到保存作者用户的模式
作者:{ 类型:Schema.Types.ObjectId,参考:'users' },
尝试在您的数据库上执行以下查询:
db.reviews.aggregate([
/** unwind in general is not needed for `$lookup` for if you wanted to match lookup result with specific elem in array is needed */
{
$unwind: { path: "$reviews", preserveNullAndEmptyArrays: true },
},
{
$lookup: {
from: "users",
localField: "reviews.author",
foreignField: "_id",
as: "author", // Pull lookup result into 'author' field
},
},
/** Update 'reviews.author' field in 'reviews' object by checking if 'author' field got a match from 'users' collection.
* If Yes - As lookup returns an array get first elem & assign(As there will be only one element returned -uniques),
* If No - keep 'reviews.author' as is */
{
$addFields: {
"reviews.author": {
$cond: [
{ $ne: ["$author", []] },
{ $arrayElemAt: ["$author", 0] },
"$reviews.author",
],
},
},
},
/** Group back the documents based on '_id' field & push back all individual 'reviews' objects to 'reviews' array */
{
$group: {
_id: "$_id",
reviews: { $push: "$reviews" },
},
},
]);
注意: 以防万一文档中有其他字段以及需要在输出中保留的 reviews
然后从 $group
开始使用这些阶段:
{
$group: {
_id: "$_id",
data: {
$first: "$$ROOT"
},
reviews: {
$push: "$reviews"
}
}
},
{
$addFields: {
"data.reviews": "$reviews"
}
},
{
$project: {
"data.author": 0
}
},
{
$replaceRoot: {
newRoot: "$data"
}
}
注意: 尝试在较小的数据集上保持对 运行 的查询,可能通过添加 $match
作为第一阶段来过滤文档并具有适当的索引。
你可以按照这个代码
$lookup:{
from:'users',
localField:'reviews.author',
foreignField:'_id',
as:'reviews.author'
}
**OR**
> When You find the doc then use populate
> reviews.find().populate("author")
我有一组这样的评论对象:
"reviews": {
"author": "5e9167c5303a530023bcae42",
"rate": 5,
"spoiler": false,
"content": "This is a comment This is a comment This is a comment.",
"createdAt": "2020-04-12T16:08:34.966Z",
"updatedAt": "2020-04-12T16:08:34.966Z"
},
我想要实现的是查找 author 字段并获取用户数据,但问题是我尝试使用的查找仅 returns这对我来说:
代码:
.lookup({
from: 'users',
localField: 'reviews.author',
foreignField: '_id',
as: 'reviews.author',
})
回复:
有什么方法可以获取作者在该领域的数据?那里是作者的id。
你应该在对服务器的请求上使用 mongoose 的 populate('author')
方法,该方法获取该作者的 id 并将用户数据添加到 mongoose 的响应中
并且不要忘记以连接这两个集合的方式设置架构
在您的审核模式中,您应该将 ref 添加到保存作者用户的模式
作者:{ 类型:Schema.Types.ObjectId,参考:'users' },
尝试在您的数据库上执行以下查询:
db.reviews.aggregate([
/** unwind in general is not needed for `$lookup` for if you wanted to match lookup result with specific elem in array is needed */
{
$unwind: { path: "$reviews", preserveNullAndEmptyArrays: true },
},
{
$lookup: {
from: "users",
localField: "reviews.author",
foreignField: "_id",
as: "author", // Pull lookup result into 'author' field
},
},
/** Update 'reviews.author' field in 'reviews' object by checking if 'author' field got a match from 'users' collection.
* If Yes - As lookup returns an array get first elem & assign(As there will be only one element returned -uniques),
* If No - keep 'reviews.author' as is */
{
$addFields: {
"reviews.author": {
$cond: [
{ $ne: ["$author", []] },
{ $arrayElemAt: ["$author", 0] },
"$reviews.author",
],
},
},
},
/** Group back the documents based on '_id' field & push back all individual 'reviews' objects to 'reviews' array */
{
$group: {
_id: "$_id",
reviews: { $push: "$reviews" },
},
},
]);
注意: 以防万一文档中有其他字段以及需要在输出中保留的 reviews
然后从 $group
开始使用这些阶段:
{
$group: {
_id: "$_id",
data: {
$first: "$$ROOT"
},
reviews: {
$push: "$reviews"
}
}
},
{
$addFields: {
"data.reviews": "$reviews"
}
},
{
$project: {
"data.author": 0
}
},
{
$replaceRoot: {
newRoot: "$data"
}
}
注意: 尝试在较小的数据集上保持对 运行 的查询,可能通过添加 $match
作为第一阶段来过滤文档并具有适当的索引。
你可以按照这个代码
$lookup:{
from:'users',
localField:'reviews.author',
foreignField:'_id',
as:'reviews.author'
}
**OR**
> When You find the doc then use populate
> reviews.find().populate("author")