【问题标题】:Retrieve sub-sub document by sub-sub document id mongoose通过子子文档 id mongoose 检索子子文档
【发布时间】:2015-07-31 10:10:30
【问题描述】:

我使用 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's find。我认为Aggregate 可能有效,但不确定如何使用Aggregate。我需要你的帮助。

更新

我已经按照@hassansin 的建议尝试了以下操作,但在控制台上它会打印空数组,并且 web 服务的响应是回复 未收到响应

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

而网络服务部分是:

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

【问题讨论】:

  • 第一个 $match 中缺少“tsList”。
  • @hassansin:现在工作正常。它正确登录控制台,而响应仍显示为No Response Received。我想我在返回结果时做错了。
  • 因为您从异步函数返回数据。见this。在gettcList 中使用callback 参数。然后返回结果,调用callback(null, result)。然后在路由器中:gettcList(req.params.tcid, function(err, result){res.json(result)});
  • @hassansin 老兄,你救了我两次。非常感谢您的帮助。

标签: javascript node.js mongodb mongoose


【解决方案1】:

使用mongodbAggregation 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"
            }
      }
])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-25
    • 2019-07-13
    • 2020-07-16
    • 1970-01-01
    • 2014-08-16
    • 2015-07-18
    • 2016-07-30
    相关资源
    最近更新 更多