hitchhiker
hitchhiker

Reputation: 1319

Why mongoose populate doesn't work when populating an array?

I have 2 schemas:

const mongoose = require('mongoose');

const PinSchema = new mongoose.Schema({
  title: String,
  content: String,
  image: String,
  latitude: Number,
  longitude: Number,
  author: {
    type: mongoose.Schema.ObjectId,
    ref: "User"
  },
  comments: [
    {
      text: String,
      createdAt: {
        type: Date,
        default: Date.now,
        author: {
          type: mongoose.Schema.ObjectId,
          ref: "User"
        }
      }
    }
  ]
}, { timestamps: true });

module.exports = mongoose.model("Pin", PinSchema);

and

const mongoose = require('mongoose');

const UserSchema = new mongoose.Schema({
  name: String,
  email: String,
  picture: String
});

module.exports = mongoose.model("User", UserSchema);

As you can see author field in Pin is the same as the _id in User schema.

I then try to populate the comments author field in the Pin schema like this:

const pinUpdated = await Pin.findOneAndUpdate(
        { _id: pinId },
        { $push: { comments: "some comment" } },
        { new: true }
      ).populate("author")
       .populate("comments.author");

however the result object has author field set to null so population doesn't work.

I'm not against doing this with native mongo syntax using $lookup but in my case it's not just looking up an array it's looking up a field of an objects array:

db.pins.aggregate([
    {
   $lookup:
     {
       from: "users",
       localField: "comments._id", // this won't work
       foreignField: "_id",
       as: "authorOutput"
     }
}    
])

what am I missing in populate()?

Upvotes: 0

Views: 353

Answers (1)

Darren G
Darren G

Reputation: 868

It looks like your author field in the comments array is nested inside the createdAt object, which is likely unintentional. Changing PinSchema to the following (closing curly brace before author) should fix it:

const PinSchema = new mongoose.Schema({
  ...
  comments: [
    {
      text: String,
      createdAt: {
        type: Date,
        default: Date.now,
      },
      author: {
          type: mongoose.Schema.ObjectId,
          ref: "User"
      }
    }
  ]
}, { timestamps: true });

Upvotes: 1

Related Questions