我是Mongo和Node的新手。我目前正在使用Mongoskin和Bluebird来处理数据库连接和查询(如此处所示:https://stackoverflow.com/a/23687958/2701348)。
我有三个馆藏:用户,粘合剂和卡片。
Binders集合包含有关每个用户的卡的信息。 Binders中的每个文档都具有以下属性:
User Id <--- that refers to the User owning the Card
Card Code <--- that refers to a Card
Count <--- that refers to the number of cards owned by the User
我更喜欢单独的卡片收藏,这样当卡片发生变化时,它会针对所有用户粘合剂进行更改。
现在我愿意为给定用户检索一个数组,例如:
[{card: {card document}, count: 4}, ...]
我有以下问题:
我知道我的以下代码是错误的,但可以作为讨论的起点:
var getAllBinderCards = function(req, res){
var db = req.db;
var userId = req.userId;
var promiseBinders = db.collection('binders').find({userId: userId}).toArrayAsync();
promiseBinders.then(function(binderCards) {
if (binderCards) {
var promiseCards;
//console.log("------ binderCards: ", binderCards);
var cards = [];
for (var i = 0; i < binderCards.length; i++) {
var binderCard = binderCards[i];
promiseCards = db.collection('cards').find({Code: binderCard.Code}).toArrayAsync();
promiseCards.then(function(cardsDB){
if(cardsDB){
//console.log("Cards found: ",binderCard.Code, cardsDB);
for (var i = 0; i < cardsDB.length; i++) {
cardsDB[i].count = binderCard.count;
};
cards.concat(cardsDB);
}
});
}
promiseCards.then(function(){
db.close();
console.log("Binder Cards: " , cards);
res.json(cards);
});
}
});
}
我正在努力弄清楚如何正确处理未满足的异步调用,以便发回整个数组并关闭数据库连接。
我想我应该尝试在for循环之前构建一个promise,并使用它来链接Cards promises上的查询,最后链接db.close()和res.json(cards)语句。
[编辑]也许最简单的解决方案是在一个 db.collection(&#39; cards&#39;)中简单地使用$ in过滤器.find({Code:{$ in:[bindersCodeArray] } to。toArrayAsync(); 并避免for循环:
var getAllBinderCards = function(req, res){
var db = req.db;
var userId = req.userId;
var promiseBinders = db.collection('binders').find({userId: userId}).toArrayAsync();
promiseBinders.then(function(binderCards) {
if (binderCards) {
var binderCodes = binderCards.map(function(element){
return element.Code;
});
var promiseCards = db.collection('cards').find({Code: {$in: binderCodes} }).toArrayAsync();
promiseCards.then(function(cards){
var bindersDictionary = {};
for (var i = 0; i < binderCards.length; i++) {
bindersDictionary[binderCards[i].Code] = binderCards[i].count;
};
for (var i = 0; i < cards.length; i++) {
cards[i].count = bindersDictionary[cards[i].Code];
};
db.close();
console.log("Binder Cards: " , cards);
res.json(cards);
});
}
});
}
我仍然很好奇是否有一种优雅的方式来使用承诺解决这个谜语。
答案 0 :(得分:1)
我希望使用$ in和array可能会限制您可以传递的绑定器数量并影响查询性能。您也可以尝试使用async#map执行此操作。 e.g:
...
function(binders) {
async.map(binders, cardsForBinders, function(err, bindersWithCards) {
// TODO: close connection here.
}
function cardsForBinders(binder, callback) {
// 1. find cards for binder.
// 2. prepare transformed response: binderWithCards.
callback(null, binderWithCards);
}
}
...