$lookup 运算符未能返回来自多个集合的组合数据
Posted
技术标签:
【中文标题】$lookup 运算符未能返回来自多个集合的组合数据【英文标题】:$lookup operator has failed to return the combined data from multiple collections 【发布时间】:2018-04-14 14:15:39 【问题描述】:我不明白为什么我的聚合管道未能合并多个集合(cmets 和用户)。我正在尝试返回 cmets 集合中每个 userId 的用户名。 MongoDB版本.... v3.0.7
.get(function(req,res)
//returning aggregate values from comments part.. comment.authorId must hv user.username.
CardComment.aggregate([ //*** qn... ask tomorrow show the models
//now perform the mongo join of multiple collections like in SQL Joins
$lookup:
from: 'users', //external collection.
localField: 'authorId', //input field., from current collection.. cardComments
foreignField: '_id', //foreign key from external collection,
as: 'commentUser'
,
//filter according to the cardId.. part. find()... first pipeline
$match:"card": req.params.cardId
], function(err,comments)
if (err)
res.json("success":false, "message": 'Error in loading comments')
else
//res.json("success": true, "message": comments)
console.log(JSON.stringify(comments))
//console.log(comments) //u need to ask for help on ***.
)
)
对于我使用 mongoose 模块的 MongoDB 模式, 我已经缩短了它以使问题更小。 cardComments 集合架构
authorId:
type: ObjectId,
ref : 'User',
required: true
,
createdAt:
type: Date,
default: Date.now
然后用于用户集合。
var UserSchema = new Schema(
username: type: String, required: true, lowercase: true, index: unique: true ,
email: type: String, required: true, index: unique: true ,
//password: type: String, required: true u forgot the select field.. that z why login was disturbing
password: type: String, select: false //that z why u need postman to test stuff
);
我有兴趣在 cmets 集合的 authorId 部分显示用户集合中的用户名字段。 谢谢
【问题讨论】:
失败了怎么办?没有结果?$lookup
失败还是 $match
失败?您是否检查过以确保 userId
实际上与外部集合中的 _id
类型相同(通常两者都需要为 ObjectId
)。最常见的错误是一个存储为“字符串”,另一个存储为ObjectId
。
在您的 comment
架构中是 card ObjectId
吗?
【参考方案1】:
如图所示,您使用了 ObjectId
的架构,它应该是像 mongoose.Schema.Types.ObjectId
这样的猫鼬 objectId。然后$lookup
应该可以工作。如果cardId
也是ObjectId
,那么您必须将其转换为猫鼬ObjectId
才能在$match
阶段使用。如果cardId
在您的comments
架构中,那么您应该首先使用$match
阶段来解决性能问题。
所以你的模型应该是这样的
authorId:
type: mongoose.Schema.Types.ObjectId,
ref : 'User',
required: true
和你的功能
get(function (req, res)
// if cardId is ObjectId type
let cardId = mongoose.Types.ObjectId(req.params.cardId);
CardComment.aggregate([
$match: "card": cardId
,
$lookup:
from: 'users',
localField: 'authorId',
foreignField: '_id',
as: 'commentUser'
], function (err, comments)
if (err)
res.json("success": false, "message": 'Error in loading comments')
else
console.log(JSON.stringify(comments))
)
)
【讨论】:
感谢您的建议。正如@Neil Lunn 所指出的,我应该检查我检查的错误消息,这似乎是数据库版本问题。 mongodb 3.0.7 不支持 $lookup。这是我检查时遇到的错误。“成功”:假,“消息”:“名称”:“MongoError”,“消息”:“异常:无法识别的管道阶段名称:'$lookup'”,“ errmsg”:“异常:无法识别的管道阶段名称:'$lookup'”,“code”:16436,“ok”:0 【参考方案2】:感谢您在我检查 $lookup 运算符的错误消息时所做的努力。感谢您的建议。正如@Neil Lunn 所指出的,我应该检查我检查的错误消息,这似乎是数据库版本问题。 mongodb 3.0.7 不支持 $lookup。这是我检查时遇到的错误。
"success": false,
"message":
"name": "MongoError",
"message": "exception: Unrecognized pipeline stage name: '$lookup'",
"errmsg": "exception: Unrecognized pipeline stage name: '$lookup'",
"code": 16436,
"ok": 0
【讨论】:
以上是关于$lookup 运算符未能返回来自多个集合的组合数据的主要内容,如果未能解决你的问题,请参考以下文章
除了 $lookup 运算符之外,MongoDB 4.0 中加入的替代方法是啥,因为它不适用于分片集合
如何在 mongodb 中使用 $lookup 加入多个集合
Mongoose.aggregate(pipeline) 使用 $unwind、$lookup、$group 链接多个集合