0

withe the following Group Schema,

group.model.js

const Role = new mongoose.Schema({
  name: { type: String, required: true }, // ensure uniqueness withn group instance using addToSet
  description: { type: String, required: false }
});

const GroupSchema = new mongoose.Schema({
  name: { type: String, index: { unique: true, required: true, dropDups: true } },
  description: { type: String, required: false },
  roles: [Role],
  createdAt: {
    type: Date,
    default: Date.now
  }
});

I am trying to list all roles ( subdocument) got a specific group

group.controller.js

function listRoles(req, res) {
  const group = req.group;
  console.log('GROUP: %j', group);
  const limit = parseInt(req.query.limit, 10) || 50;
  const skip = parseInt(req.query.skip, 10) || 0;

  Group.aggregate([
    { $match: { _id: req.params.groupId } },
    { $unwind: '$roles' },
    { $skip: skip },
    { $limit: limit }
  ], (err, result) => {
    if (err) {
      res.status(500);
      res.json({ message: 'Error. Cannot list roles', errror: err });
    }
    res.status(200);
    console.log('RESULT: %j', result);
    res.json(result);
  });
}

I should get an array with one role, but I get an empty array what's wrong with my aggregate code ? thanks for feedback

note: I tried to aggregate only with the $match in the pipe and I also get an empty array... so I guess. the issue comes from the req.params.groupId should be an ObjectId .. how can I cast it ?

console.log

GROUP: {"_id":"5923e2e83afd4149bdf16c61","name":"Admin","description":"Administration group","__v":1,"createdAt":"2017-05-23T07:21:12.470Z","roles":[{"name":"Role1","description":"description role1","_id":"5923e2e83afd4149bdf16c62"}]}

RESULT: []
  • Run mongod like this: `mongo -vvvv` and see what kind of query your program is making. – arboreal84 May 23 '17 at 07:34
  • the issue seems to be related to the fact that I am using req.params.groupId as a value for _id in the match which is a string... and not an ObjectId .. can I cast it ? –  May 23 '17 at 07:54
  • Take a look at: https://stackoverflow.com/questions/6578178/node-js-mongoose-js-string-to-objectid-function – arboreal84 May 23 '17 at 07:55

1 Answers1

0

To better diagnose this, I'd recommend removing steps from your aggregation pipeline and seeing what the result is. However, I suspect your problem is because you have no match at the first stage because you're comparing a string to an ObjectId. Try this:

const mongoose = require('mongoose')

// and in the aggregation:

{ $match: { _id: mongoose.Types.ObjectId(req.params.groupId) } }
richsilv
  • 7,993
  • 1
  • 23
  • 29
  • thanks that's what I suspected... effectively I did not thought about 'comparing' ... it's the first time I am using aggregate and I thought the cats was performed automatically... thanks –  May 23 '17 at 08:03
  • yeah, it is pretty surprising first time! FWIW if you're comparing `ObjectId`s in JS you need to use `objectIdA.equals(objectIdB)` as `objectIdA === objectIdB` always returns `false`, even if they look the same stringified. That was about two hours wasted for me first time round... – richsilv May 23 '17 at 09:40