David Verdugo
David Verdugo

Reputation: 33

Mongoose - populate object that contains other fields

I have an array of objects. I want to save certain portions in the collection, and reference a second collection to retrieve supplementary data

Collection 1

statute: [{
    _id: { type: ObjectId, ref: "Statute" },
    subsection: [{
      header: String,
    }],
}],

Using .populate("statute._id", "title statute") I was hoping to get the following output:

"statute": [
    {
        "subsection": [],
        "_id": "5c15bcf348549e2aac5e99d3",
        "title": 13,
        "statute": 103
    },
 ]

But the output I am receiving is

"statute": [
        {
            "subsection": [],
            "_id": {
                "_id": "5c15bcf348549e2aac5e99d3",
                "title": 13,
                "statute": 103
            }
        },

How do I tell Mongoose to populate based on statute._id but return the values in statute?

Upvotes: 0

Views: 89

Answers (1)

BenSower
BenSower

Reputation: 1612

As far as I know, this is not possible in this way, since it would mean adding/overwriting fields in a schema, which makes it impossible for mongoose to know what to do with these fields when you hit .save() on an object created like this.

However, unless you need an actual mongoose object as a result, you can use the aggregate function with some lookup + projection magic, something like this (you'll probably have to adapt to your doc structure, though):

statute.aggregate([
 { $match : {}},
 { $unwind: '$statute'} // splitting the array into separate fields
 {
   $lookup: // see https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/
     {
       from: 'Statute',
       localField: '_id',
       foreignField: '_id,
       as: 'remote_statute'
     }
 },
 {
   $project: {
    "subsection": '$subsection',
    "_id": "$remote_statute._id",
    "title": '$remote_statute.title',
    "statute": '$remote_statute.statute'
   }
 }
])

Note: You'll probably have to add a group-stage to merge the results back together into an array. If you don't know what the exact fields of statute will look like, you can also have a look at the $replaceRoot function to be applied to the populated statute, but I feel like this doesn't fit your use-case.

Also, I'd suggest you rename the _id field to something more descriptive like statuteId, since this might otherwise interfere with the _id fields set by mongoose.

Upvotes: 1

Related Questions