并行查询使用dynamic集合/模型

这是使用Mongoose和Async

我在一个async.parallel调用中引用了多个函数,他们基本上是这样的:

 var winston = require('winston'), async = require('async'), //Mongo Models Product = require('../models/product'), Runway = require('../models/runway'), Conversion = require('../models/conversion'), Engagement = require('../models/engagement'); var user = { email: req.params.email }; var score = { product: null, runway: null, conversion: null, engagement: null }; var scoreInfo = 'email score'; findProductByID = function(id, filter, callback) { Product.findOne(id, filter).sort({ field: 'asc', _id: -1 }).limit(1).exec(function(err, docs) { if (docs !== undefined && docs !== null && docs.score !== undefined && docs.score !== null) { score.product = docs.score; console.log("Product Score for " + user.email + " : " + score.product); callback(null, score.product); } else { console.log("Product score not found, setting to 0"); score.product = 0; callback(null, score.product); } }); }; findRunwayByID = function(id, filter, callback) { Runway.findOne(id, filter).sort({ field: 'asc', _id: -1 }).limit(1).exec(function(err, docs) { if (docs !== undefined && docs !== null && docs.score !== undefined && docs.score !== null){ score.runway = docs.score; console.log("Runway Score for " + user.email + " : " + score.runway); callback(null, score.runway); } else { console.log("Runway score not found, setting to 0"); score.runway = 0; callback(null, score.runway); } }); }; findConversionByID = function(id, filter, callback) { Conversion.findOne(id, filter).sort({ field: 'asc', _id: -1 }).limit(1).exec(function(err, docs) { if (docs !== undefined && docs !== null && docs.score !== undefined && docs.score !== null){ score.conversion = docs.score; console.log("Conversion Score for " + user.email + " : " + score.conversion); callback(null, score.conversion); } else { console.log("Conversion score not found, setting to 0"); score.conversion = 0; callback(null, score.conversion); } }); }; findEngagementByID = function(id, filter, callback) { Engagement.findOne(id, filter).sort({ field: 'asc', _id: -1 }).limit(1).exec(function(err, docs) { if (docs !== undefined && docs !== null && docs.score !== undefined && docs.score !== null){ score.engagement = docs.score; console.log("Engagement Score for " + user.email + " : " + score.engagement); callback(null, score.engagement); } else { console.log("Engagement score not found, setting to 0"); score.engagement = 0; callback(null, score.engagement); } }); }; async.parallel([ async.apply(findProductByID, user, scoreInfo), async.apply(findRunwayByID, user, scoreInfo), async.apply(findConversionByID, user, scoreInfo), async.apply(findEngagementByID, user, scoreInfo), ], function(err, result) { res.json(score); }); 

};

我试图使用方括号来访问属性,所以我可以写一个函数来执行4个任务,如下所示:

 findScoresByID = function(type, id, filter, callback) { [type].findOne(id, filter).sort({ field: 'asc', _id: -1 }).limit(1).exec(function(err, docs) { if (docs !== undefined && docs !== null && docs.score !== undefined && docs.score !== null){ score[type] = docs.score; console.log("Score for " + user.email + " : " + score[type]); callback(null, score[type]); } else { console.log("Score not found, setting to 0"); score[type] = 0; callback(null, score[type]; } }); }; async.parallel([ async.apply(findScoresByID, "product", user, scoreInfo), async.apply(findRunwayByID, "runway", user, scoreInfo), async.apply(findRunwayByID, "conversion", user, scoreInfo), async.apply(findRunwayByID, "engagement", user, scoreInfo), ], function(err, result) { res.json(score); }); 

除了读取[type].findOne...的第二行之外 ,这个工作中的所有内容[type].findOne...

当我尝试使用这个(即使是一个硬编码的名字,如["engagement"].findOne...而不是[type]的variables/参数)我得到一个错误,读取TypeError: ["engagement"].findOne is not a function (另外,删除点完全导致“意外标识符”错误)

我已经阅读了StackOverflow的前面的例子,似乎使用这种方式,我打算,但我似乎无法得到它的工作。 任何帮助将不胜感激! 谢谢=)

实际上,在假定如何dynamic使用mongoose模型时,实际上存在一个基本的错误,但是在所有的代码中还可以清除其他一些东西。

所以首先你不需要asyncjs ,所以把它扔掉是因为nodejs完成了所有你需要的操作。

第二种情况是,一旦他们已经被注册,就不必为了这个目的而单独导入模型。 只要代码的一部分已经调用模型来注册它们,那么我们在这里不需要再次导入。

假设你在注册模型时一致地命名事物,如:

 module.exports = mongoose.model('Product', productSchema); 

然后,我们可以通过与注册相同的名称来返回模型。 如:

 Promise.all( ["Product","Runway","Conversion","Engagement"].map(name => mongoose.model(name).findOne( { email: req.params.email }, 'score -_id' ) .sort({ field: 'asc', _id: -1 }) .then( data => ({ [name.toLowerCase()]: (data) ? data.score : 0 }) ) ) ) .then( result => res.json(result.reduce((acc,curr) => Object.assign(acc,curr),{})) ) .catch(err => console.error(err)); // Or something with error 

或者如果你真的坚持使用async.parallel来做同样的事情

 async.parallel( ["Product","Runway","Conversion","Engagement"].map(name => ({ [name.toLowerCase()]: (callback) => mongoose.model(name).findOne( { email: req.params.email }, 'score -_id' ) .sort({ field: 'asc', _id: -1 }) .exec((err,data) => { if (err) callback(err); callback(null, (data) ? data.score : 0); } ) })) .reduce((acc,curr) => Object.assign(acc,curr),{}), (err,result) => { if (err) throw err; // or do something res.json(result); } ) 

按名称调用模型是最有意义的,因为您希望在返回对象的输出键中使用相同的名称(当然是小写)。

当然,如果你仍然想要使用它们,那么只需稍作改动:

  [Product,Runway,Conversion,Engagement].map(model => ({ [model.name.toLowerCase()]: (callback) => model.findOne( 

这真的是所有的。 在Promises版本当然没有callback的类似用法,但你应该得到一般的想法。 它也很清楚地表明你最初对“variables”的误解是什么。

不同的方法实际上只有Promise.all正在运行从列表产生的一系列承诺。 async.parallel正在运行一个名为keys的对象,每个对象都提供了一个调用每个模型结果的包装函数。

所以响应对象在Promise.all的返回结果之后被构造,而在Promise.all的情况下则是“在…之中”。 但两者本质上都是在“并行”运行查询。