如何立即执行mongoose查询并使用Promise.all等待它们?

时间:2017-08-29 12:42:41

标签: javascript node.js mongodb mongoose bluebird

我只是习惯了承诺,我想在表格中添加额外的ObjectId引用。我使用这段代码:

'use strict';

const mongoose = require('mongoose');
const config = require('config');

mongoose.connect(config.get("DBUrl"), {useMongoClient: true});
mongoose.set('debug', true);

require('../model/AnnotationRequest');
require('../model/Website');

const AnnotationRequest = mongoose.model('AnnotationRequest');
const Website = mongoose.model('Website');

foo(function () {
    console.log('done');
});

function foo(done) {

    Website.find()
        .then(function (websites) {
            if (!websites) console.error('could not find any websites');

            AnnotationRequest.find({website: {$exists: false}})
                .then(function (annotationRequests) {

                    let jobs = [];

                    for (let k = 0; k < annotationRequests.length; k++) {
                        let found = false;

                        for (let i = 0; i < websites.length; i++) {
                            let websiteAnnotations = websites[i].annotations;

                            for (let o = 0; o < websiteAnnotations.length; o++) {

                                if (websiteAnnotations[o].equals(annotationRequests[k].annotation)) {
                                    found = true;
                                    annotationRequests[k].website = websites[i];
                                    jobs.push(
                                        annotationRequests[k].save()
                                            .then(function (res) {
                                                console.log("success saving", res._id);
                                            }).catch(function (err) {
                                                console.error(err);
                                                done(err);
                                            })
                                    );
                                    break;
                                }
                            }
                            if (found) {
                                break;
                            }
                        }
                    }

                    Promise.all(jobs).then(
                        function () {
                            done();
                        }
                    ).catch(function (err) {
                        console.error(err);
                    });
                });
        });
}

报告第一个保存查询是在Promise.all语句中启动的。在第一个.save()语句之后是否应该立即执行查询?我怎样才能立即启动它们?

另一个问题是,对于200k条目,此代码需要2个小时。在服务器上我们有&gt; 2M条目。不确定它是否会起作用。有什么建议吗?

由于

1 个答案:

答案 0 :(得分:2)

节点运行单线程,因此如果您有200k循环,则所有保存语句都会等待,直到您的代码同步执行并完成。

尝试使用异步模块使您的代码更加异步友好。 https://caolan.github.io/async/

尝试此代码,但此代码与您的代码有相同的错误。我有一个网站有相同的注释,你的设置首先找到,我可能最后找到。

'use strict';

const mongoose = require('mongoose');
const config = require('config');
const async = require('async');


mongoose.connect(config.get("DBUrl"), {useMongoClient: true});
mongoose.set('debug', true);

require('../model/AnnotationRequest');
require('../model/Website');

const AnnotationRequest = mongoose.model('AnnotationRequest');
const Website = mongoose.model('Website');

foo(function () {
    console.log('done');
});

function foo(done) {

    const pageSize= 10000;

    async.parallel([function(callback) {

        Website.find().then( function(websites) {
            callback(null, websites);
        }).catch(callback);

    },function(callback) {
        AnnotationRequest.count({website: {$exists: false}}).then( function(count) {
            callback(null, count);
        }).catch(callback);
    }], function(err, results) {

        if(err) {
            console.error(err);
            return;
        }

        const websites = results[0];
        const annotationRequestsCount = results[1];

        let websiteAnnotationMap = {};

        websites.forEach(function (website) {
            website.annotations.forEach(function (annotation) {
                websiteAnnotationMap[annotation] = website;
            });
        });


        var skip = 0;

        async.during(
            function (callback) {
                return callback(null, skip < annotationRequestsCount);
            },
            function (callback) {

                AnnotationRequest.find({website: {$exists: false}},  { skip: skip, limit: pageSize })
                    .then( function(annotationRequests) {

                        skip += pageSize;

                        async.each(annotationRequests, function(annotationRequest, eachCallback) {

                            let website = websiteAnnotationMap[annotationRequest.annotation];
                            if(website) {
                                annotationRequest.website = website;
                                annotationRequest.save().then(function () {
                                    eachCallback();
                                }).catch(eachCallback);

                            } else {
                                eachCallback();
                            }
                        }, callback);
                }).catch(callback);
            },
            done
        );


    });
}