通过子文档id mongoose检索子子文档

时间:2015-07-30 23:13:14

标签: javascript node.js mongodb mongoose

我使用Mongoose,Express和Node。

我有四种模式:

Step.js

var StepSchema = new mongoose.Schema({ ... });
module.exports = StepSchema;

TC.js

var Step = require('Step');
var TCSchema = new mongoose.Schema({ stepList: [Step] });
module.exports = TCSchema;

TS.js

var TC = require('TC');
var TSSchema = new mongoose.Schema({ tcList: [TC] });
module.exports = TSSchema;

TR.js

var TS = require('TS');
var TRSchema = new mongoose.Schema({ tsList: [TS] });
module.exports = mongoose.model('TR', TRSchema);

示例数据

{
   _id: ObjectId("32d33ddf54de3")
   tsList: [
      {
          _id: ObjectId("66d4f66d44f88")
          tcList: [
              {
                  _id: ObjectId("8df84ff8fssdeg")
                  stepList: [
                      {
                          _id: ObjectId("5484kkfci393d")
                      }
                  ]
              }
          ]
      }
   ]
}

现在我想使用这样的id检索我的tcList,例如:

http://localhost:3000/api/tc/8df84ff8fssdeg

预期输出为:

{
    _id: ObjectId("8df84ff8fssdeg")
    stepList: [
      {
          _id: ObjectId("5484kkfci393d")
      }
    ]
}

我完全不知道如何在这里建立我的 mongoose find。我认为Aggregate可能有用,但不确定如何使用Aggregate。我需要你的帮助。

更新

我已经按照@hassansin的建议尝试了以下操作,但在控制台上它会打印出空数组,而webservice的响应会回复没有收到响应

var gettcList = function(tcId) {
    TR.aggregate(
        [

            // match by tcList _id and reduce the no of documents for the next pipeline stages
            {
                $match: {
                    "tsList.tcList._id": mongoose.Types.ObjectId(tcId)
                }
            },

            // deconstruct tsList array
            {
                $unwind: "$tsList"
            },

            // deconstruct tcList array
            {
                $unwind: "$tsList.tcList"
            },

            // match again in the deconstructed document list
            {
                $match: {
                    "tsList.tcList._id": mongoose.Types.ObjectId(tcId)
                }
            },

            // project the fields
            {
                $project: {
                    _id: "$tsList.tcList._id",
                    stepList: "$tsList.tcList.stepList"
                }
            }

        ], function(err, result) {
            if (err) {
                console.log(err);
                return next(err);
            }
            console.log(result);
            return result;
        }
    );
};

Web服务部分是:

router.get('/tc/:tcid', function(req, res, next) {
    res.json(gettcList(req.params.tcid));
});

1 个答案:

答案 0 :(得分:1)

使用mongodb Aggregation Pipeline

db.collection.aggregate([
      //match by tcList _id and reduce the no of documents for the next pipeline stages
      {$match : {'tsList.tcList._id': ObjectId("55bab42fb768129caa039b4b") } },
      //deconstruct tsList array
      {$unwind: '$tsList'},
      //deconstruct tcList array
      {$unwind: '$tsList.tcList'},
      //match again in the deconstructed document list
      {$match : {'tsList.tcList._id': ObjectId("55bab42fb768129caa039b4b") } },
      //project the fields
      {$project : 
            {     
                  _id: "$tsList.tcList._id",
                  stepList : "$tsList.tcList.stepList"
            }
      }
])