简体   繁体   English

MongoDB和NodeJS从3个集合中获取相关数据

[英]MongoDB and NodeJS get related data from 3 collections

i have a mongoDB query to get data with $group and $count. 我有一个mongoDB查询来获取$ group和$ count的数据。 This data contains the _id from other documents collection. 此数据包含来自其他文档集合的_id。 How can i get the other documents by its _id in NodeJS and MongoDB asyncrohnous? 我如何通过NodeJS和MongoDB中的_id异步获取其他文档?

 db.orders.aggregate([
                 {$match: { 'works.TechnicianId': {$in:['53465f9d519c94680327965d','5383577a994be8b9a9e3f01e']}, 
                           'works.Date': {$gte: ISODate("2013-05-21T06:40:20.299Z"), $lt: ISODate("2016-05-21T06:40:20.299Z")}}},
                 {$unwind: "$works" },
                 {$group: {_id: "$works.TechnicianId",total:{$sum:'$works.price'},ordersId: { $push: "$_id" }}},
                   ])

This is the result: 结果如下:

    {
    "result" : [ 
        {
            "_id" : "53465f9d519c94680327965d",
            "total" : 198,
            "ordersId" : [ 
                ObjectId("537b5ea4c61b1d1743f4341f"), 
                ObjectId("537b4633021d75bd36863f29")
            ]
        }, 
        {
            "_id" : "5383577a994be8b9a9e3f01e",
            "total" : 22,
            "ordersId" : [ 
                ObjectId("537b5ea4c61b1d1743f4341f"), 
                ObjectId("537b4633021d75bd36863f29")
            ]
        }
    ],
    "ok" : 1
}

Now i need to get from orders collection the documents with id from ordersId, and from other collection the documents with _id from the result _id field. 现在,我需要从订单集合中获取具有来自ordersId的id的文档,并从其他集合中获取来自结果_id字段的具有_id的文档。

I try with this: 我尝试这样:

var collection = db.collection('orders');
    var result = [];

    collection.aggregate([
            {
                $match: {
                    'works.TechnicianId': {
                        $in: ids
                    },
                    'works.Date': {
                        $gte: new Date(startDate),
                        $lt: new Date(endDate)
                    }
                }
            },
            {
                $unwind: "$works"
            },
            {
                $group: {
                    _id: "$works.TechnicianId",
                    total: {
                        $sum: '$works.price'
                    },
                    orderId: {
                        $push: "$_id"
                    }
                }
            }
        ],
        function (e, docs) {
            if (e) {
                error(e);
            }
            var usersCollection = db.collection('users');

            _.each(docs, function (doc) {
                usersCollection.findOne({_id: new ObjectID(doc._id)}, function (e, doc) {
                    doc.tech = doc;
                });
                doc.orders = [];
                _.each(doc.orderId, function (queryOrder) {
                    collection.findOne({_id: new ObjectID(queryOrder._id)}, function (e, order) {
                        doc.orders.push(order);
                    });
                });
                success(docs);
            });
        });

But the success its called before all the _.eachs are finished..Any help, or idea? 但是成功要在所有_.each都完成之前调用。.有什么帮助或想法吗?

Edit: 编辑:

I try with Q promises, this is my code: 我尝试使用Q promises,这是我的代码:

 var usersCollection = db.collection('users');
            var promises = [];

            _.each(reports, function (report) {
                var promise = usersCollection.findOne({_id: new ObjectID(report._id)}).then(
                    function (e, orderUserReported) {
                        if (e) {
                            error(e);
                        }
                        report.tech = orderUserReported;
                        _.each(orderUserReported.orderId, function (queryOrder) {
                            collection.findOne({_id: new ObjectID(queryOrder._id)}, function (e, order) {
                                report.orders.push(order);
                            });
                        });
                    });
                promises.push(promise);
            });
            Q.allSettled(promises).then(success(reports));

and the error: 和错误:

/Users/colymore/virteu/aa/server/node_modules/mongodb/lib/mongodb/connection/base.js:245
        throw message;      
              ^

TypeError: Cannot call method 'then' of undefined TypeError:无法调用未定义的方法“ then”

Because of asynchronous execution you have to wait until results are returned. 由于异步执行,您必须等到返回结果。 There are several options available: 有几种可用的选项:

  1. async library https://github.com/caolan/async 异步库https://github.com/caolan/async
  2. promises https://github.com/kriskowal/q 承诺https://github.com/kriskowal/q

Async is closer to your current code, you could use async.parallel https://github.com/caolan/async#parallel to wait untill you get data back 异步更接近您当前的代码,您可以使用async.parallel https://github.com/caolan/async#parallel来等待,直到您获得数据

Update 更新

Mongoose functions don't return Q promises, so you need to convert mongoose calls to promises by using something like Q.denodeify(User.findOne.bind(models.User))({ _id: userId}).then(... 猫鼬函数不会返回Q许诺,因此您需要使用Q.denodeify(User.findOne.bind(models.User))({ _id: userId}).then(...

For your case Q.denodeify(userCollection.findOne.bind(userCollection))({_id: new ObjectID(report._id)}).then(... 对于您的情况Q.denodeify(userCollection.findOne.bind(userCollection))({_id: new ObjectID(report._id)}).then(...

Short answer: Use promises. 简短的答案:使用承诺。 Look at Q.allSettled ( https://github.com/kriskowal/q ) Just run success asynchronously when all subtask are done. 查看Q.allSettled( https://github.com/kriskowal/q )当所有子任务都完成时,异步运行成功。

Also using https://github.com/iolo/mongoose-q package may be helpful to not combine mongoose promises with Q ones if you want use mongoose in your mongo. 如果您想在您的mongo中使用猫鼬,也可以使用https://github.com/iolo/mongoose-q软件包将不将猫鼬的承诺与Q的承诺相结合可能会有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM