【问题标题】:Query with Mongoose multiple times without nesting多次使用 Mongoose 查询而不嵌套
【发布时间】:2021-01-03 02:59:33
【问题描述】:

我正在尝试使用 node.js 生成一个文档,该文档需要从 mongo 数据库运行多个不相关的数据库查询。

这是我当前的代码:

Data.find({}, function(err, results) {
  if (err) return next(err);
  //finished getting data
    res.render('page');
  }
}

问题是如果我尝试运行另一个查询,我似乎必须将它嵌套在第一个查询中,以便它在开始之前等待第一个查询完成,然后我必须将 res.render() 放入其中最里面的嵌套查询(如果我不这样做,将在数据库完成抓取数据之前调用 res.render(),并且不会与页面一起呈现)。

我必须做的:

Data.find({}, function(err, results) {
  if (err) return next(err);
  //finished getting data

    Data2.find({}, function(err, results2) {
      if (err) return next(err);
      //finished getting data 2
        res.render('page');
      }
    }
  }
}

我将有超过 2 个查询,所以如果我继续嵌套它们,它会很快变得非常混乱。有没有更简洁的方法来做到这一点,例如让代码等到所有数据返回并运行函数后再继续执行脚本?

【问题讨论】:

  • 用例是什么?您想要两个查询的所有结果还是数据以某种方式“关联”?两种情况都有不同的答案。看起来您实际上正在使用mongoose,但如果您确认这一点会很好。
  • 是的,我正在使用猫鼬。数据不相关,我正在尝试创建站点地图,有些我只是为各种数据集生成 url 列表。
  • 您认为提供的答案中是否有某些内容无法解决您的问题?如果是这样,那么请对答案发表评论,以澄清究竟需要解决哪些尚未解决的问题。如果它确实回答了您提出的问题,请注意Accept your Answers您提出的问题。
  • Promise 是不必要的,只会让代码更加混乱。只需使用异步。

标签: node.js mongodb mongoose


【解决方案1】:

对于 mongoose,您可能只需执行 Promise.all() 并在每个查询的结果数组上使用 .concat()

作为一个完整的演示:

var async = require('async'),
  mongoose = require('mongoose'),
  Schema = mongoose.Schema;

var d1Schema = new Schema({ "name": String });
var Data1 = mongoose.model("Data1", d1Schema);

var d2Schema = new Schema({ "title": String });
var Data2 = mongoose.model("Data2", d2Schema);

mongoose.set('debug',true);
mongoose.connect('mongodb://localhost/test');

async.series(
  [
    // Clean
    function(callback) {
      async.each([Data1,Data2],function(model,callback) {
        model.remove({},callback)
      },callback);
    },
    // Setup some data
    function(callback) {
      async.each([
        { "name": "Bill", "model": "Data1" },
        { "title": "Something", "model": "Data2" }
      ],function(data,callback) {
        var model = data.model;
        delete data.model;
        mongoose.model(model).create(data,callback);
      },callback);
    },
    // Actual Promise.all demo
    function(callback) {
      Promise.all([
        Data1.find().exec(),
        Data2.find().exec()
      ]).then(function(result) {
        console.log([].concat.apply([],result));
        callback()
      }).catch(callback);
    }
  ],
  function(err) {
    if (err) throw err;
    mongoose.disconnect();
  }
)

为了简洁起见,我只是在这里混入async,但它的核心在于:

  Promise.all([
    Data1.find().exec(),
    Data2.find().exec()
  ]).then(function(result) {
    console.log([].concat.apply([],result));
  })

Promise.all() 基本上等待并组合这两个结果,这将是一个“数组数组”,但.concat() 负责处理。结果将是:

[ 
  { _id: 59420fd33d48fa0a490247c8, name: 'Bill', __v: 0 },
  { _id: 59420fd43d48fa0a490247c9, title: 'Something', __v: 0 }
]

显示每个集合中的对象,并在一个数组中连接在一起。

您也可以使用 async.concat 方法作为替代方法,但除非您已经在使用该库,否则最好还是遵守承诺。

【讨论】:

  • 所以 promise 基本上只是一个 javascript 函数,它等待一个或多个其他函数完成,然后在它们全部完成后运行一个函数?
  • @stackers 这可能最好通过阅读可用材料来回答。这是Promise 的MDN 定义。但或多或少你的定义是基本的总结。 Promise.all 正如答案中的链接所描述的那样,专门等待传递给它的 all Promise 对象来解析并返回数组中的组合结果。正如答案所说,我们.concat() 到单个数组。本质上,我们将所有“回调”合二为一。
猜你喜欢
  • 2019-04-01
  • 2014-08-05
  • 1970-01-01
  • 1970-01-01
  • 2021-04-26
  • 2012-10-17
  • 2012-06-23
  • 2013-06-03
  • 1970-01-01
相关资源
最近更新 更多