【问题标题】:make nested mongodb queries faster使嵌套的 mongodb 查询更快
【发布时间】:2020-02-11 22:55:56
【问题描述】:

这个函数在 getinitialprops 上触发,它等待它在渲染之前完成。与等待这个长查询完成相比,有什么方法可以提高速度?

exports.getAppStats = (req, res, next) => {
  const startToday = moment(req.query.today).startOf('day');
  const endToday = moment(req.query.today).endOf('day');
  const startsevenDays = moment(req.query.today).subtract(7, 'd').startOf('day');
  const startThirtyDays = moment(req.query.today).subtract(30, 'd').startOf('day');
  const startYear = moment(req.query.today).subtract(365, 'd').startOf('day');

  const stats = {}
  Application.countDocuments({ dateTime: { $gte: startToday, $lte: endToday } })
    .then((result) => {
      stats.today = result
      Application.countDocuments({ dateTime: { $gte: startsevenDays, $lte: endToday } })
      .then((result) => {
        stats.sevenDays = result
        Application.countDocuments({ dateTime: { $gte: startThirtyDays, $lte: endToday } })
        .then((result) => {
          stats.thirtyDays = result
          Application.countDocuments({ dateTime: { $gte: startYear, $lte: endToday } })
          .then((result) => {
            stats.year = result
            return res.json(stats);
          }).catch(err => console.log(err))
        }).catch(err => console.log(err))
      }).catch(err => console.log(err))
    }).catch(err => console.log(err))
}

【问题讨论】:

    标签: javascript node.js mongodb express


    【解决方案1】:

    在这里您可以利用Promise.all() 函数并行运行所有查询,然后等待所有查询完成,如下所示:

    exports.getAppStats = (req, res, next) => {
      const startToday = moment(req.query.today).startOf('day');
      const endToday = moment(req.query.today).endOf('day');
      const startsevenDays = moment(req.query.today).subtract(7, 'd').startOf('day');
      const startThirtyDays = moment(req.query.today).subtract(30, 'd').startOf('day');
      const startYear = moment(req.query.today).subtract(365, 'd').startOf('day');
    
      const stats = {}
      // get promises for each query
      let today = Application.countDocuments({ dateTime: { $gte: startToday, $lte: endToday } });
      let sevenDays = Application.countDocuments({ dateTime: { $gte: startsevenDays, $lte: endToday } });
      let thirtyDays = Application.countDocuments({ dateTime: { $gte: startThirtyDays, $lte: endToday } });
      let year = Application.countDocuments({ dateTime: { $gte: startYear, $lte: endToday } });
      // wait until all promises have been resolved, then set stats & send response
      Promise.all([today, sevenDays, thirtyDays, year]).then(([todayData, sevenDaysData, thirtyDaysData, yearData]) => {
        stats = {
          today: todayData,
          sevenDays: sevenDaysData,
          thirtyDays: thirtyDaysData,
          year: yearData
        }
        res.status(200).json({data: stats});
      }, (err) => {
        console.log(err);
        // next(err);
        // res.status(500).json({ message: "Something went wrong..." });
      });
    }
    

    或者,您可以使用async/await 关键字来完全避免回调。尽管它需要try/catch 来处理错误。老实说,这没什么区别,这纯粹是偏好。

    // note this is now an async function
    exports.getAppStats = async (req, res, next) => {
      const startToday = moment(req.query.today).startOf('day');
      const endToday = moment(req.query.today).endOf('day');
      const startsevenDays = moment(req.query.today).subtract(7, 'd').startOf('day');
      const startThirtyDays = moment(req.query.today).subtract(30, 'd').startOf('day');
      const startYear = moment(req.query.today).subtract(365, 'd').startOf('day');
    
      // get promises for each query
      let today = Application.countDocuments({ dateTime: { $gte: startToday, $lte: endToday } });
      let sevenDays = Application.countDocuments({ dateTime: { $gte: startsevenDays, $lte: endToday } });
      let thirtyDays = Application.countDocuments({ dateTime: { $gte: startThirtyDays, $lte: endToday } });
      let year = Application.countDocuments({ dateTime: { $gte: startYear, $lte: endToday } });
      try {
        // wait until all promises have been resolved, then set stats & send response
        // await Promise.all instead of using callbacks
        let [todayData, sevenDaysData, thirtyDaysData, yearData] = await Promise.all(
          [today, sevenDays, thirtyDays, year]
        );
        let stats = {
          today: todayData,
          sevenDays: sevenDaysData,
          thirtyDays: thirtyDaysData,
          year: yearData
        }
        res.status(200).json({data: stats});
      } catch(err) {
        console.log(err);
        // next(err);
        // res.status(500).json({ message: "Something went wrong..." });
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-06-20
      • 1970-01-01
      • 2015-05-20
      • 1970-01-01
      • 2015-11-19
      • 2020-02-26
      • 1970-01-01
      • 2019-11-11
      • 1970-01-01
      相关资源
      最近更新 更多