在 express (async/await) 中使用一个 mongoose 查询的输出作为另一个查询的输入

Posted

技术标签:

【中文标题】在 express (async/await) 中使用一个 mongoose 查询的输出作为另一个查询的输入【英文标题】:Using output of one mongoose query for the input of another in express (async/await) 【发布时间】:2020-04-16 21:46:58 【问题描述】:

我正在使用 express 和 mongoose 来实现服务器/数据库。我有一条工作路线,可以通过 playerID 获取所有涉及玩家的游戏。我现在正在尝试实现一个可以使用用户名而不是 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);

这是我必须通过 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 );
  
);

以下概述了我想要做的事情,但它不起作用,原因有很多:

我试图先从用户名中获取 userId,然后将其传递给游戏查询。

//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 );
  
);

我一直在阅读有关 .populate()、promise 和瀑布的内容,但我是新手,希望得到一些指导!

【问题讨论】:

【参考方案1】:

请试试这个:

//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 );
    
);

【讨论】:

谢谢!这行得通!你能解释一下为什么会这样而我的不会吗? @emsha :正如我在回答中所说,如果找不到匹配的文档,mongoDB 不会抛出错误,它将在.findOne() 上返回null && [] 在@987654325 上@。所以基本上我们只是使用if 块验证我们的数据库结果而不是检查实际错误,所有实际错误都将被catch 块捕获,而且我想我忘了把await 放在@987654329 行之前@,你可以在你的代码中包含..

以上是关于在 express (async/await) 中使用一个 mongoose 查询的输出作为另一个查询的输入的主要内容,如果未能解决你的问题,请参考以下文章

使用 async/await 时在 Express 中捕获未处理的异常

Express 和 async/await:我应该用 try/catch 包装吗?

Node/Express 和 MongoDB:Async/Await 与 Model.create()

Async/await mvc express 使用 .catch() 处理错误的问题

为啥 async / await 函数运行两次?

通过 async/await 从 Node 中的 redis 同步获取