4

This is my document structure:

{
"_id": "590dc8b17e52f139648b9b94",
"parent": [
    {
        "_id": "590dc8b17e52f139648b9b95",
        "child": [
            {
                "_id": "590dc8b17e52f139648b9b8f"
            },
            {
                "_id": "590dc8b17e52f139648b9b90"
            }
        ]
    },
    {
        "_id": "590dc8c57e52f139648b9b9b",
        "child": [
            {
                "_id": "590dc8c57e52f139648b9b96"
            }
        ]
    }
]}

I'm trying to return only the information about the nested object which i'm looking for with its _id.

router.get('/child/:id', (req, res) => {
    Project.findOne({ 'parent.child._id': req.params.id },
            (err, results) => {
                    if (err)
                            res.status(500).send(err);
      res.status(200).json(results.parent[0].child.id(req.params.id));

            }
    )});

the problem is that results contains the entire document which may contain multiple instances of parent So obviously my code only works if the known child _id it's in the first parent.

How can i fix it? many thanks

so apparently the unwind and match solution is good but for mongoose you need to explicitly say that the id is an ObjectId type.

 {$match:
{ "parent.child._id": new mongoose.Types.ObjectId(id) }
            }

found it here

Community
  • 1
  • 1
Gianluca Gini
  • 66
  • 1
  • 1
  • 5

1 Answers1

5

Basically You can $unwind the parent first in an aggregate and then match with child id. This will make sure it gives you just the parent object and not entire document. Also if matching id need not be inside the first parent object but it can be anywhere inside parent object array. It will return the require object from parent array which contains search id in its child array.

db.project.aggregate([ 
    { $unwind : '$parent'},
    { $match : 
        { "parent.child._id" : '590dc8b17e52f139648b9b8f' } 
    } 
]);

Mongooese Syntax :

//mongoose

let Project = mongoose.model('project', yourProjectSchema);

Project.aggregate([ 
    { "$unwind" : '$parent'},
    { "$match" : 
        { "parent.child._id" : req.params.id } 
    } 
]);
Mihir Bhende
  • 8,677
  • 1
  • 30
  • 37
  • thanks, i'm still trying to understand why i receive an empty array as result – Gianluca Gini May 07 '17 at 15:15
  • Are you receiving an empty array after the aggregate workaround I mentioned above? Also make sure you replace the static id I had mentioned with your requirements parameter – Mihir Bhende May 07 '17 at 15:18
  • yes i tried both with an existing hardcoded id and the actual one coming the request parameters. Also i had to change db.project.aggregate into Project.aggregate as i'm using mongoose – Gianluca Gini May 07 '17 at 15:25
  • Can you check in mongo shell by trying above query and a hardcoded id which exists in your child._id values? I have added mongoose syntax in answer as well. – Mihir Bhende May 07 '17 at 15:52
  • 1
    Thanks, i solved it by adding: new mongoose.Types.ObjectId(id) – Gianluca Gini May 07 '17 at 16:18