简体   繁体   中英

Populating Virtual Field in Mongoose

I'm currently building an application that logs poker statistics. Users create players and then populate games with those players.

I have a games model which references the players from the player model:

const gameSchema = new mongoose.Schema({
  firstPlace: { type: mongoose.Schema.ObjectId, ref: 'Players', required: true },
  secondPlace: { type: mongoose.Schema.ObjectId,ref: 'Players', required: true },
  thirdPlace: { type: mongoose.Schema.ObjectId, ref: 'Players', required: true },
  fourthPlace: { type: mongoose.Schema.ObjectId, ref: 'Players' },
  fifthPlace: { type: mongoose.Schema.ObjectId, ref: 'Players' },
  sixthPlace: { type: mongoose.Schema.ObjectId, ref: 'Players' },
  seventhPlace: { type: mongoose.Schema.ObjectId, ref: 'Players' },
  eighthPlace: { type: mongoose.Schema.ObjectId, ref: 'Players' },
  ninthPlace: { type: mongoose.Schema.ObjectId, ref: 'Players' },
  buyIn: { type: Number, required: true },
  firstPrize: { type: Number, required: true },
  secondPrize: { type: Number, required: true },
  thirdPrize: { type: Number, required: true },
  date: { type: String },
  notes: { type: String },
  userId: { type: mongoose.Schema.ObjectId, ref: 'Users', required: true },
})

To get the information on a single game, I populate the references to players -

// Get single Game
async function getSingleGame(req, res, next) {
  try {
    const { gameId } = req.params
    const foundGame = await Games.findById(gameId)
      .populate('userId')
      .populate('firstPlace')
      .populate('secondPlace')
      .populate('thirdPlace')
      .populate('fourthPlace')
      .populate('fifthPlace')
      .populate('sixthPlace')
      .populate('seventhPlace')
      .populate('eighthPlace')
      .populate('ninthPlace')
    if (!foundGame) throw new NotFound()
    return res.status(200).json(foundGame)
  } catch (err) {
    next(err)
  }
}

This works well, so for example firstPlace is populated with an object that contains all the information of that player.

However, I have a virtual field on my user model which gets all the games that user has created. Code below -

userSchema
  .virtual('addedGames', {
    ref: 'Games',
    localField: '_id',
    foreignField: 'userId',
  })
  .get(function (addedGames) {
    if (!addedGames) return
    return addedGames.map((game) => {
      return {
        _id: game._id,
        firstPlace: game.firstPlace,
        secondPlace: game.secondPlace,
        thirdPlace: game.thirdPlace,
        fourthPlace: game.fourthPlace,
        fifthPlace: game.fifthPlace,
        sixthPlace: game.sixthPlace,
        seventhPlace: game.seventhPlace,
        eigthPlace: game.eigthPlace,
        ninthPlace: game.ninthPlace,
        buyIn: game.buyIn,
        firstPrize: game.firstPrize,
        secondPrize: game.secondPrize,
        thirdPrize: game.thirdPrize,
      }
    })
  })

This works - but all the placings are objectIds rather than the objects themselves. My question is - how can I populate these references to Players on this virtual field?

Thanks in advance, I've been pulling my hair out over this!

After much trial and error, I added this to populate the nested objects -

let user = await User.findById(currentUserId)
  .populate('addedPlayers')
  .populate([
    {
      path: 'addedGames',
      populate: {
        path: 'firstPlace secondPlace thirdPlace fourthPlace fifthPlace sixthPlace seventhPlace eighthPlace',
      },
    },
  ])

Originally I just had populate('addedGames')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM