$ lookup运算符无法从多个集合中返回组合数据

时间:2017-11-02 06:19:46

标签: node.js mongodb mongoose

我不知道为什么我的聚合管道无法组合多个集合(注释和用户)。我试图在评论集合中返回每个userId的用户名。 MongoDB版本.... v3.0.7

.get(function(req,res){
      //returning aggregate values from comments part.. comment.authorId must hv user.username.
       CardComment.aggregate([ //stackoverflow 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 stackoverflow.
         }
       })

    })

使用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
});

我有兴趣在comments集合的authorId部分显示users集合中的用户名字段。 谢谢

2 个答案:

答案 0 :(得分:0)

如您所使用的ObjectId架构所示,它应该是像mongoose.Schema.Types.ObjectId这样的mongoose objectId。然后$lookup应该有效。如果cardId也是ObjectId,则必须将其转换为mongoose 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))
    }
  })
})

答案 1 :(得分:0)

感谢您在我查看$ 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
}

}