Query with Mongoose multiple times without nesting

牧云@^-^@ 提交于 2019-12-12 17:07:39

问题


I'm trying to generate a document with node.js that needs to run multiple unrelated database queries from a mongo database.

Here is my current code:

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

The problem is if I try to run another query, I seem to have to nest it within the first one so that it waits for the first one to finish before starting, and then I have to put res.render() within the innermost nested query (if I don't, res.render() will be called before the database is finished grabbing data, and it wont be rendered with the page).

What I have to do:

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');
      }
    }
  }
}

I am going to have more than 2 queries, so if I keep nesting them it's going to get really messy really fast. Is there a cleaner way to do this, such as a way to make the code wait until all the data is returned and the function is run before continuing with the script?


回答1:


For mongoose you can probably just do a Promise.all() and use .concat() on the resulting arrays of each query.

As a full demo:

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();
  }
)

I'm just mixing in async there for brevity of example, but the meat of it is in:

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

Where the Promise.all() basically waits for and combines the two results, which would be an "array of arrays" here but the .concat() takes care of that. The result will be:

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

Showing the objects from each collection, joined together in one array.

You could also use the async.concat method as an alternate, but unless you are using the library already then it's probably just best to stick to promises.



来源:https://stackoverflow.com/questions/44556790/query-with-mongoose-multiple-times-without-nesting

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!