Reputation: 101
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?
Upvotes: 9
Views: 5851
Reputation: 164
2024 - Mongoose version 8
There is a better and simpler way to achieve this:
PlaylistModel.find()
.populate({
path: 'videos',
model: 'Video',
select: 'title',
foreignField: 'externalId',
})
_id
)Upvotes: 2
Reputation: 2573
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
})
Upvotes: 9