mongodb聚合中的多个$ lookup阶段

时间:2017-03-04 04:48:07

标签: mongodb mongoose

我正在使用以下mongoose schemas

问题架构:

var Question = new Schema({
  title: String,
  content: String,
  createdBy: {
      type: Schema.ObjectId,
      ref: 'User',
      required: true
    },
  answers: {
     type: [ { type: Schema.Types.ObjectId, ref: 'Answer' } ]
   }
});

回答Shchema:

var Answer = new Schema({
      content: {
            type: String,
            require: 'Content cannot be empty.'
       },
        createdBy: {
            type: Schema.Types.ObjectId,
            ref: 'User'
       },
       isBest: {
            type: Boolean,
            default: false
        },
        createdAt: {
        type: Date,
        default: Date.now
       },
         votes: {
         type: Number,
         default: 0
       },
        comments: {
        type: [{ type: Schema.Types.ObjectId, ref: 'Comment' }]
       }
    });

评论架构:

var Comment = new Schema({
     content: {
     type: String,
     required: [true, 'Content cannot be empty']
    },
    createdBy: {
    type: Schema.Types.ObjectId,
    ref: 'User'
   },
    createdAt: {
    type: Date,
    default: Date.now
   }
});

基本上我要做的是在每个$lookup中为answerscomments数组执行answer,然后在$project阶段如果用户登录的是isOwnertrue所有者,请尝试添加answer字段comment。这就是我的尝试:

Question.aggregate([
  {
    $match: { '_id': { $eq: questionId } }
  },
  {
    $lookup: {
      from: 'answers',
      localField: 'answers',
      foreignField: '_id',
      as: 'answers'
    }
  },{
    $lookup:{
      from: 'comments',
      localField: 'answers.comments',
      foreignField: '_id',
      as: 'comments'
    }
  }, {
    $project: {
      title: true,
      content: true,
      createdBy: true,
      createdAt: true,
      isOwner: { $eq : ['$createdBy', currentUser] },
      answers: true,
      answers: {
        isOwner: { $eq : ['$createdBy', currentUser] },
        content: true,
        createdBy: true,
        createdAt: true,
        comments: {
          content: true,
          createdAt: true,
          createdBy: true,
          isOwner: { $eq : ['$createdBy', currentUser] }
        }
      }
    }
  }
])

这是我期待的输出:

{
"_id": "58a7be2c98a28f18acaa4be4",
"title": "Some title",
"createdAt:": "2017-03-03T05:13:41.061Z",
"content": "some content",
"isOwner": true,
"createdBy": {
    "_id": "58a3a66c088fe517b42775c9",
    "name": "User name",
    "image": "imgUrl"
},
"answers": [
    {
        "_id": "58a3a66c088fe517b42775c9",
        "content": "an answer content",
        "createdAt": "2017-03-03T05:13:41.061Z",
        "isBest": false,
        "isOwner": false,
        "createdBy":{
            "_id": "58a3a66c088fe517b42775c9",
            "name": "another user",
            "image": "another image"
        },
        "comments": [
            {
                "_id": "58aa104a4254221580832a8f",
                "content": "some comment content",
                 "createdBy": {
                    "_id": "58a3a66c088fe517b42775c9",
                    "name": "another user",
                    "image": "another image"
                },
            }
        ]
    }
]
 }

我正在使用mongodb 3.4.2

2 个答案:

答案 0 :(得分:1)

您的代码存在的问题是您在查找之前没有展开answeeres数组 请查看以下评论​​

Question.aggregate([
  {
    $match: { '_id': { $eq: questionId } }
  },
  {
    $lookup: {
      from: 'answers',
      localField: 'answers',
      foreignField: '_id',
      as: 'answers'
    }
  },
  {$unwind : "$answers"},   // <-- Check here
  {
    $lookup:{
      from: 'comments',
      localField: 'answers.comments',
      foreignField: '_id',
      as: 'comments'
    }
  }, 

  {
  $group : {

  _id : null,
   title: {$first : true},
      content: {$first :true},
      createdBy: {$first :true},
      createdAt: {$first :true},
      isOwner: { $eq : ['$createdBy', currentUser] },
      answersStatus: {$first :true},
        answers : {$push : $answer}
    }
  }
])

答案 1 :(得分:1)

您可以尝试addFields阶段为所有关系添加isOwner字段。

Question.aggregate([{
    $match: {
        '_id': {
            $eq: questionId
        }
    }
}, {
    $addFields: {
        "isOwner": {
            $eq: ['$createdBy', currentUser]
        }
    }
}, { // No unwind needed as answers is scalar of array values.
    $lookup: {
        from: 'answers',
        localField: 'answers',
        foreignField: '_id',
        as: 'answers'
    }
}, {
    $addFields: {
        "answers.isOwner": {
            $eq: ['$createdBy', currentUser]
        }
    }
}, {
    $unwind: "$answers" //Need unwind here as comments is array of scalar array values 
}, {
    $lookup: {
        from: 'comments',
        localField: 'answers.comments',
        foreignField: '_id',
        as: 'comments'
    }
}, {
    $addFields: { 
        "comments.isOwner": {
            $eq: ['$createdBy', currentUser]
        }
    }
}, {
    $addFields: { // Move the comments back to answers document
        "answers.comments": "$comments"
    }
}, {
    $project: { // Remove the comments embedded array.
        "comments": 0
    }
}, {
    $group: {
        _id: null,
        isOwner: {
            $first: "$isOwner"
        },
        answers: {
            $push: "$answers"
        }
    }
}])