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

How to execute mongoose queries immediately and wait for them with Promise.all?

我刚刚习惯了 promises,我想添加一个额外的 ObjectId 引用到 table。我使用此代码:

'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() 语句之后立即执行查询?我怎样才能立即启动它们?

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

谢谢

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

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

试试这个代码,但是这个代码和你的有同样的错误。 ID 不止一个网站有相同的注释,你的设置最先找到,我的可能最后找到。

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


    });
}