0

I use Mongoose, Express and Node.

I have my four schemas:

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

Example Data:

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

Now I would like to retrieve my tcList using the id like this for ex:

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

The expected output is:

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

I'm totally not aware on how to build my mongoose's find here. I'm thinking that Aggregate may work, but unsure on how to use Aggregate. I need your help.

Update

I've tried the following as suggested by @hassansin, but on console it prints empty array and the response of webservice is replying back with No response received:

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

And the web service part is:

router.get('/tc/:tcid', function(req, res, next) {
    res.json(gettcList(req.params.tcid));
});
Vimalraj Selvam
  • 2,155
  • 3
  • 23
  • 52
  • missing 'tsList' in the first $match. – hassansin Jul 31 '15 at 01:55
  • @hassansin: This is working fine now. It properly logs in the console, whereas the response is still showing as `No Response Received`. I guess I'm doing something wrong while returning the result. – Vimalraj Selvam Jul 31 '15 at 02:15
  • 1
    because you are returning data from asynchronous function. See [this](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call?rq=1). take a `callback` argument in `gettcList `. Then instead returning result, call `callback(null, result)`. Then in router: `gettcList(req.params.tcid, function(err, result){res.json(result)});` – hassansin Jul 31 '15 at 02:26
  • @hassansin dude you saved me twice. Thanks a lot for the help. – Vimalraj Selvam Jul 31 '15 at 05:02

1 Answers1

1

Use 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"
            }
      }
])
hassansin
  • 16,918
  • 3
  • 43
  • 49