Search code examples
mongodbexpressmongoosemongoose-schema

Using output of one mongoose query for the input of another in express (async/await)


I am using express and mongoose to implement a server/db. I have a working route that gets all the games involving a player by playerID. I am now trying to implement one that can take username instead of playerID.

PLAYER_SCHEMA:

const mongoose = require('mongoose');

const PlayerSchema = mongoose.Schema( {
  username: {
    type:String,
    required:true,
    unique:true
  },
  date_registered: {
    type: Date,
    default:Date.now
  }
});

module.exports = mongoose.model('Player', PlayerSchema);

GAME_SCHEMA:

const mongoose = require('mongoose');

const GameSchema = mongoose.Schema( {
  player_1: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Player',
    required: true
  },
  player_2: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Player',
    required: true
  },
  status: {
    type:String,
  },
  hero_1: {
    type:String
  },
  hero_2: {
    type:String
  },
  date_registered: {
    type: Date,
    default:Date.now
  }

});

module.exports = mongoose.model('Game', GameSchema);

Here's what I have to query all games involving a player by playerId:

//GET GAMES INVOLVING PLAYER BY PLAYER_ID
router.get('/player/:playerId', async (req, res) => {
  try {
    const games = await Game.find({$or:[{ player_1: req.params.playerId }, { player_2: req.params.playerId}]});
    console.log(games)
    res.json(games);
    // weird cuz doesn't throw error if not found, just returns empty list...
  }
  catch (err) {
    res.json({ message: err });
  }
});

The following outlines what I want to do, but it doesn't work, for I'm sure many reasons:

I am trying to get the userId from username first, then pass that into a query for the games.

//GET ALL GAMES ASSOCIATED WITH PLAYER BY USERNAME
router.get('/username/:username', async (req, res) => {
  try {
    const player = await Player.findOne({username:req.params.username});
    console.log(player);
    const games =  Game.find({ $or:[{ player_1: player._id }, { player_2: player._id }] });
    res.json(games);
  }
  catch (err) {
    res.json({ message: err });
  }
});

I've been reading about .populate(), promises, and waterfalls, but I'm new to this and would love some guidance!


Solution

  • Please try this :

    //GET ALL GAMES ASSOCIATED WITH PLAYER BY USERNAME
    router.get('/username/:username', async (req, res) => {
        try {
            const player = await Player.findOne({ username: req.params.username });
            console.log(player);
            /**
             * .findOne() should return a document or null - if no match found..
             */
            if (player) {
                /**
                 * .find() will return empty [] only if it didn't find any matching docs but won't throw an error in successful DB operation
                 * (irrespective of whether docs matched or not, if op is successful then there will be no error).
                 */
                const games = await Game.find({ $or: [{ player_1: player._id }, { player_2: player._id }] }).lean();
                (games.length) ? res.json(games) : res.json(`No games found for ${player._id}`);
            } else {
                res.json('No player found')
            }
        }
        catch (err) {
            res.json({ message: err });
        }
    });