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

标签 javascript node.js mongodb mongoose bluebird

我刚刚习惯了 Promise,我想向表添加一个额外的 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 小时。在服务器上,我们有超过 2M 的条目。不确定它是否会起作用。有什么建议吗?

谢谢

最佳答案

Node 运行单线程,因此如果您有 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
        );


    });
}

关于javascript - 如何立即执行 mongoose 查询并使用 Promise.all 等待它们?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45939482/

相关文章:

mongodb - Mongoengine:如何将新文档 append 到嵌入式ListField文档?

mongodb - docker-compose mongo 需要所有人的读取权限

mongodb - Mongo maxTimeMS 不会立即终止查询

javascript - 在哪里可以找到有关 Javascript 引擎内部结构的信息?

javascript - jQuery 想要覆盖按钮单击的功能

node.js - linux重启后nodejs消失了

node.js - 我该如何处理服务器上的所有错误,使其永不崩溃?

javascript - iOS 旋转照片问题

javascript - jQuery .offset() 没有检索到正确的位置

javascript - 如何在node.js中查找页面上的所有链接?