mongoose: populate in mongoose which doesn't have any ObjectId

元气小坏坏 提交于 2020-05-16 03:54:27

问题


I have 2 schemas as shown

const gameSchema = new mongoose.Schema({
    title: String,
    rating: { type: Number, min: 0, max: 100 },
    genres: { type: Array, ref: 'Genres' }
})
const GenreSchema = new mongoose.Schema({
    id: { type: Number },
    name: String,
    description: String
})
mongoose.model('Games', gameSchema)
mongoose.model('Genres', GenreSchema)

Now one endpoint /api/games returns an array of results from games where genres property contains array of id eg. "genres": [4, 7, 19]

How do I populate genres without any ObjectId? I've tried with normal ref method but it says

{"stringValue":"\"4\"","kind":"ObjectId","value":4,"path":"_id","reason":{},"message":"Cast to ObjectId failed for value \"4\" at path \"_id\" for model \"Genres\"","name":"CastError"}

I want to point it to id instead of _id


回答1:


You can use the concept of Virtuals. Here how it goes:

Modify your schema file as following:

//---------------------------------------------------
const gameSchema = new mongoose.Schema({
  title: String,
  rating: { type: Number, min: 0, max: 100 },
  genres: [Number],//here you have an array of id of type Number as yours, no ref
});
const GenreSchema = new mongoose.Schema({
  id: { type: Number },
  name: String,
  description: String,
});

gameSchema.virtual("games", {
  ref: "Genres",//this is the model to populate
  localField: "id",//the field used to make the populate, it is the field that must match on the aimed  Genres model <- here is the trick you want!!!  
  foreignField: "genres",//the field to populate on Games model
  justOne: false,
});

 gameSchema.set("toObject", { virtuals: true });//if you are planning to use say console.log
 gameSchema.set("toJSON", { virtuals: true });//if you are planning to use say res.json

mongoose.model("Games", gameSchema);
mongoose.model("Genres", GenreSchema);
//-------------------------------------------------

On the file you are trying to populate, put this in the declaration section:

//-----------------------------------------------------
const Games = mongoose.model("Games", gameSchema);
//---------------------------------------------------

Last but not least, where you want to populate:

//----------------------------------------------
Games.find({})
  .populate("games")
  .exec(function (error, games) {
   //with games you can use things like game.field1, it is actually an JSON object! Print out games and see the fieds for your self, select one and call it using the dot notation! 
    console.log(games);
  });
//---------------------------------------------

I have tested this solution on a problem I had done, just modified to fit your needs, please, let me know if it works in yours; if not, we can figure it out together how to fit my solution to meet your needs.

Some initial references

  1. Populate a mongoose model with a field that isn't an id


来源:https://stackoverflow.com/questions/61174212/mongoose-populate-in-mongoose-which-doesnt-have-any-objectid

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!