如何在循环多个 db.Phrase.find 调用时使用回调从 mongodb 正确传递数据
How to properly pass data from mongodb using callback when looping through multiple db.Phrase.find calls
我从 get 请求中收到如下所示的参数:
{ location: 'Venice', weather: 'Dry', what: 'Yoga', who: 'Bob' }
然后我查询一个 mongodb 数据库,该数据库循环遍历每个键和值对并查询它们在数据库中的并集。
然后我将返回值保存到 outputCaption,然后使用回调将 outputCaption 传回。
问题是回调被调用的次数与其键值对循环的次数一样多。
我被迫这样做,因为我需要 db.Phrase.find 调用中的回调,但我调用了多次...
所以我使用 app.get 中的代码修复了它(我等到所有键都在 outputCaption 中定义了值,然后再做任何事情)
它有效,但我无法想象这是最好的方法,所以我希望有一种不那么骇人听闻的方法?
谢谢
server.js
var express = require('express');
var db = require('./modules/db')
var logic = require('./modules/logic')
...
app.get('/phrase', function(req, res){
logic(req.query, function(outputCaption){
var flag = true
for (key in outputCaption){
if (outputCaption[key] === null){
console.log('Incomplete')
var flag = false;
}
}
if (flag === true) {
console.log(outputCaption);
};
});
})
...
logic.js
var db = require('./db')
var logic = function(params, callback){
var outputCaption = {
who: null,
what: null,
location: null,
weather: null
};
for (key in params){
category = key.toLowerCase();
option = params[key].toLowerCase();
db.Phrase.find({$and: [
{category: category},
{option: option}
]}, function(err, phrases){
if (err) return console.error(err);
var options = Object.keys(phrases).length
var idxOfOptionPicked = Math.floor(Math.random() * options)
outputCaption[phrases[idxOfOptionPicked].category] = phrases[idxOfOptionPicked].phrase
callback(outputCaption)
})
}
}
module.exports = logic;
与其触发多个查询并在客户端执行结果的并集,不如使用查询运算符允许 MongoDB
为您执行并集。
这样你:
- 避免多次访问数据库。
- 避免多个回调处理程序。
- 可以 post 在单个回调处理程序中处理结果。
您可以修改代码以根据请求参数准备查询对象,
var params = {location: 'Venice', weather: 'Dry', what: 'Yoga', who: 'Bob' };
var query = {};
var conditions = [];
Object.keys(params).forEach(function(key){
var $and = {};
$and["category"] = key.toLowerCase();
$and["option"] = params[key];
conditions.push($and);
});
(conditions.length > 1)?(query["$or"] = conditions):(query = conditions[0]);
现在构建的查询如下所示:
{ '$or':
[ { category: 'location', option: 'Venice' },
{ category: 'weather', option: 'Dry' },
{ category: 'what', option: 'Yoga' },
{ category: 'who', option: 'Bob' }
]
}
您可以将此对象传递给 find()
方法,以一次性获得结果:
db.Phrase.find(query,callback);
这样您的代码就会更加清晰易懂。
我从 get 请求中收到如下所示的参数:
{ location: 'Venice', weather: 'Dry', what: 'Yoga', who: 'Bob' }
然后我查询一个 mongodb 数据库,该数据库循环遍历每个键和值对并查询它们在数据库中的并集。
然后我将返回值保存到 outputCaption,然后使用回调将 outputCaption 传回。
问题是回调被调用的次数与其键值对循环的次数一样多。
我被迫这样做,因为我需要 db.Phrase.find 调用中的回调,但我调用了多次...
所以我使用 app.get 中的代码修复了它(我等到所有键都在 outputCaption 中定义了值,然后再做任何事情)
它有效,但我无法想象这是最好的方法,所以我希望有一种不那么骇人听闻的方法? 谢谢
server.js
var express = require('express');
var db = require('./modules/db')
var logic = require('./modules/logic')
...
app.get('/phrase', function(req, res){
logic(req.query, function(outputCaption){
var flag = true
for (key in outputCaption){
if (outputCaption[key] === null){
console.log('Incomplete')
var flag = false;
}
}
if (flag === true) {
console.log(outputCaption);
};
});
})
...
logic.js
var db = require('./db')
var logic = function(params, callback){
var outputCaption = {
who: null,
what: null,
location: null,
weather: null
};
for (key in params){
category = key.toLowerCase();
option = params[key].toLowerCase();
db.Phrase.find({$and: [
{category: category},
{option: option}
]}, function(err, phrases){
if (err) return console.error(err);
var options = Object.keys(phrases).length
var idxOfOptionPicked = Math.floor(Math.random() * options)
outputCaption[phrases[idxOfOptionPicked].category] = phrases[idxOfOptionPicked].phrase
callback(outputCaption)
})
}
}
module.exports = logic;
与其触发多个查询并在客户端执行结果的并集,不如使用查询运算符允许 MongoDB
为您执行并集。
这样你:
- 避免多次访问数据库。
- 避免多个回调处理程序。
- 可以 post 在单个回调处理程序中处理结果。
您可以修改代码以根据请求参数准备查询对象,
var params = {location: 'Venice', weather: 'Dry', what: 'Yoga', who: 'Bob' };
var query = {};
var conditions = [];
Object.keys(params).forEach(function(key){
var $and = {};
$and["category"] = key.toLowerCase();
$and["option"] = params[key];
conditions.push($and);
});
(conditions.length > 1)?(query["$or"] = conditions):(query = conditions[0]);
现在构建的查询如下所示:
{ '$or':
[ { category: 'location', option: 'Venice' },
{ category: 'weather', option: 'Dry' },
{ category: 'what', option: 'Yoga' },
{ category: 'who', option: 'Bob' }
]
}
您可以将此对象传递给 find()
方法,以一次性获得结果:
db.Phrase.find(query,callback);
这样您的代码就会更加清晰易懂。