2017-07-11 11 views
1

ソフトウェアにエラーがあり、mongodbの参照が壊れていました。 例のウェブサイトのドキュメント:配列のたObjectIdのいくつかはもはや存在しないmongodb配列から壊れた参照を削除するには?

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

。 私は、アノテーションオブジェクトへの壊れた参照を削除する方法を見つけようとしています。 これは私がやろうとしているものです:

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

私はPromise.allの作業を取得することはできません。それはfind関数の.thenの前に実行されます。 どうすればわかりましたか。

普通のmongodbを使用してこれを行うには、もっとエレガントな方法がありますか?

は、これは本当に答えが、私はAsync.jsとLodashを使用してそれを行うだろうかの一般的な考え方ではありません

+0

{_ ID:ここ は終わりで働いていたものです{$で: website.annotations}}) '次に、クエリの結果を元のリストと比較します。競合状態が心配していない場合は、結果の配列にwebsite.annotationsを設定するだけです。 おそらく2つの配列の違いを簡単に見つけるためにlodashを見てみましょう(それらを比較する前に必ず.toString()objectIdsを確認してください) promise.allの代わりにここで非同期またはストリームを使用することを検討しますウェブサイトは大きくなる可能性があります) – Andreas

答えて

0

質問の例が機能しない理由はわかりません。しかし:(などAnnotation.find `としてクエリを作る私が代わりに(website.annotationsのannotationId)forループ、第2をスキップしてしまう

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); 
       }); 
     } 
    }); 
0

ありがとうございました。

私は実際にブルーバードを使用していません(ドキュメントの見た目では、私はこれからも疑います)。

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

ObjectIDの2つの配列を比較する際に問題がありました。そのため、私はObjectIDの2つの配列を比較していました。

関連する問題