Mongoose: Populate path using field other than _id

Viewed 2529

By default mongoose/mongo will populate a path using the _id field, and by it seems like there is no way to change the _id to something else.

Here are my two models which are connected with one-to-many relationship:

const playlistSchema = new mongoose.Schema({
  externalId: String,
  title: String,
  videos: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Video',
  }],
});

const videoSchema = new mongoose.Schema({
  externalId: String,
  title: String,
});

Normally, when querying a playlist you would populate videos just with .populate('videos'), but in my case I would like to use the externalId field instead of the default _id. Is that possible?

1 Answers

As far as I know, the way to achieve this with mongoose presently is by using virtuals. When populating virtuals, you can specify the localField and foreignField to whatever you want, so you are no longer bound to the default _id as foreignField. More details about this here.

For the scenario described in your question, you would need to add a virtual to the playerlistSchema, something like this:

playlistSchema.virtual('videoList', {
  ref: 'Video', // The model to use
  localField: 'videos', // The field in playerListSchema
  foreignField: 'externalId', // The field on videoSchema. This can be whatever you want.
});

Now, whenever you query for player lists, you can populate the videoList virtual to get the referenced video documents.

PlaylistModel
  .findOne({
    // ... whatever your find query needs to be
  })
  .populate('videoList')
  .exec(function (error, playList) {
    /* if a playList document is returned */
    playList.videoList; // The would be the populated array of videos
  })
Related