javascript - 关闭 mongodb 连接并通过多个并行异步查询获得正确结果

标签 javascript node.js mongodb bluebird mongoskin

我是 Mongo 和 Node 的新手。我目前正在使用 Mongoskin 和 Bluebird 来处理数据库连接和查询(如此处建议:https://stackoverflow.com/a/23687958/2701348)。

我有三个集合:用户、 Binder 和卡片。

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

我更喜欢有一个单独的 Cards 集合,这样当 Card 发生变化时,它会针对所有 Users Binders 发生变化。

现在我愿意为给定用户检索一个数组,例如:

[{card: {card document}, count: 4}, ...]

我有以下问题:

  • 在调用所有异步数据库回调后应关闭数据库连接
  • 应该在最后一个db.collection('cards').find返回结果后返回cards数组

我知道我的以下代码是错误的,但可以作为讨论的起点:

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

我正在努力弄清楚如何正确处理 promise 的异步调用,以便发回整个数组并关闭数据库连接。

我认为我应该尝试在 for 循环之前构建一个 promise,并使用它来链接 Cards promises 上的查询,最后链接 db.close() 和 res.json(cards) 语句。

[编辑] 也许最简单的解决方案是在单个 db.collection('cards').find({Code: {$in: [bindersCodeArray] }}).toArrayAsync 中简单地使用 $in 过滤器(); 并避免 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);
            });

        }
    });
}

我仍然很好奇是否有一种使用 promises 来解决这个谜题的优雅方法。

最佳答案

我预计使用 $in 和 array 可能会限制您可以传递的绑定(bind)器数量并影响查询性能。您也可以尝试使用 async#map 执行此操作.例如:

...

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

...

关于javascript - 关闭 mongodb 连接并通过多个并行异步查询获得正确结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26432211/

相关文章:

javascript - 点击时设置 Cookie

javascript - 如何制作汇总模块,重新导出ESM模块的所有子模块导出?

ajax - 使用 ajax 和 nodejs 服务器不会更改 session cookie

javascript - 即使confirm()方法为false,Jquery AJAX也会提交表单

javascript - 在没有预定义函数的情况下合并两个数组在javascript中

javascript - 在javascript弹出窗口中显示php页面

c# - 通过界面投影

node.js - 自动更新 NodeJS 应用程序中的 package.json

node.js - PassportJS 重命名 "user"对象

python - Mongoose Schemas 和通过 python 插入