简体   繁体   English

如何从mongodb数组中删除损坏的引用?

[英]How to delete broken references from mongodb array?

I had an error in my software leading to broken references in my mongodb. 我的软件出现错误,导致mongodb中的引用损坏。 An example website document: 一个示例网站文档:

{
"_id" : ObjectId("58d55766f12ba71c4131468a"),
"name" : "abc",
"annotations" : [ 
  ObjectId("58d5580b507af01cc77c5155"), 
  ObjectId("58d55888b83e461d768fc0eb"), 
  ObjectId("58d8d0b434f0b621272869be"), 
  ObjectId("58d8d0f034f0b621272869bf")
]

Where some of the ObjectIds in the array don't exist any more. 数组中某些ObjectId不再存在的地方。 I'm trying to find a way to delete the broken references to the annotation object. 我正在尝试找到一种方法来删除对注释对象的损坏的引用。 This is what I'm trying to do: 这就是我想要做的:

const mongoose = require('mongoose');
const config = require('config');
const Promise = require('bluebird');
mongoose.Promise = Promise;

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

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

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


Website.find({})
    .then(function (websites) {

        for (let website of websites) {

            let queue = [];

            for (let annotationId of website.annotations) {

                queue.push(Annotation.find({_id: annotationId}, {_id: 1})
                    .then(function (ann) {
                        if (!ann) {
                            website.pull(annotationId);
                        }
                        return Promise.resolve(website);
                    })
                );
            }

            Promise.all(queue)
                .then(function (ws) {
                    console.log('updated website ' + website.name)
                    return website.save();
                })
                .catch(function (err) {
                    throw new Error(err);
                });
        }
    });

I can't get the Promise.all working. 我无法实现Promise.all。 It's executed before the .then of the find functions. 它在find函数的.then之前执行。 Please help me to find the error. 请帮助我找到错误。

Is there maybe a more elegant way to do this using plain mongodb? 使用纯mongodb可能有更优雅的方法吗?

Thank You 谢谢

This is not really an answer but a general idea of how I would do it using Async.js and Lodash. 这不是一个真正的答案,而是关于我将如何使用Async.js和Lodash进行操作的总体思路。

I don't really use Bluebird (and by the looks of their documentation, I doubt I ever will). 我并没有真正使用Bluebird(从他们的文档来看,我怀疑我会不会使用)。

async.series([
    // get all annotation IDs
    done => Annotation.distinct('_id').exec(done),
    // get all websites
    done => Website.find({}).exec(done)
], function (err, results) {
    let annotationIDs = results[0].map(String), 
        websites = results[1];
    // loop through each website
    async.eachSeries(websites, function (website, done) {
        // reset the annotations with only ones that exist
        website.annotations = _.intersection(website.annotations.map(String), annotationIDs)
        website.save(done);
    }, function (err) => {
        // all done
    });
});

I've had issues comparing two arrays of ObjectIDs, so I cast them to Strings just in case. 比较两个ObjectID数组时遇到问题,因此我将它们强制转换为String以防万一。

I'm not sure why the example in the question doesn't work. 我不确定问题中的示例为何不起作用。 But: Here is what worked in the end: 但是:这是最终有效的方法:

Website.find({})
    .then(function (websites) {

        for (let website of websites) {

            let queue = [];

            for (let annotationId of website.annotations) {

                queue.push(Annotation.find({_id: annotationId}, {_id: 1})
                    .then(function (ann) {
                        if (!ann) {
                            website.pull(annotationId);
                        }
                        return Promise.resolve(website);
                    })
                );
            }

            Promise.all(queue)
                .then(function (ws) {
                    console.log('updated website ' + website.name)
                    return website.save();
                })
                .catch(function (err) {
                    throw new Error(err);
                });
        }
    });

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

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