복붙노트

[MONGODB] 다른 컬렉션에 하나 개의 컬렉션에서 MongoDB를 이동 문서

MONGODB

다른 컬렉션에 하나 개의 컬렉션에서 MongoDB를 이동 문서

어떻게 문서는 MongoDB의 다른 컬렉션에 하나 개의 컬렉션 이동할 수 있습니다 ?? 예를 들면 : 나는 수집 A의 문서를 많이하고 난 (이 1개월 오래된 문서를 수집 (A)에 안) 수집 B에 대한 모든 1개월 오래된 문서를 이동하려는.

우리가 사본을 할 수 집계 사용. 하지만 내가 뭘하려고 문서의 이동이다. 어떤 방법은 문서를 이동할 수 있습니다?

해결법

  1. ==============================

    1.업데이트 2

    업데이트 2

    더 이상이 답변을 upvote에하지 마십시오. jasongarber의 대답 @ 작성된 모든 측면에서 낫다.

    최신 정보

    @jasongarber의이 대답은 안전한 방법입니다 대신 나의 사용해야합니다.

    내가 바로 당신이있어 당신은 모든 문서를 세 1 개월 이상을 이동하려면, 당신은 MongoDB를 2.6 사용할 제공하지 내가 알고 있는데 여러 작업을 수행하는 가장 효율적인 방법을 사용 벌크 작업에 이유가 없다 :

    > var bulkInsert = db.target.initializeUnorderedBulkOp()
    > var bulkRemove = db.source.initializeUnorderedBulkOp()
    > var date = new Date()
    > date.setMonth(date.getMonth() -1)
    > db.source.find({"yourDateField":{$lt: date}}).forEach(
        function(doc){
          bulkInsert.insert(doc);
          bulkRemove.find({_id:doc._id}).removeOne();
        }
      )
    > bulkInsert.execute()
    > bulkRemove.execute()
    

    이것은 꽤 빨리해야하고 경우에 뭔가 대량 삽입하는 동안 잘못 있다는 장점이있다, 원본 데이터는 여전히 존재합니다.

    편집하다

    너무 많은 메모리를 방지하기 위해 이용 될하기에서 처리 된 모든 X의 문서에 대량 작업을 실행할 수있다 :

    > var bulkInsert = db.target.initializeUnorderedBulkOp()
    > var bulkRemove = db.source.initializeUnorderedBulkOp()
    > var x = 10000
    > var counter = 0
    > var date = new Date()
    > date.setMonth(date.getMonth() -1)
    > db.source.find({"yourDateField":{$lt: date}}).forEach(
        function(doc){
          bulkInsert.insert(doc);
          bulkRemove.find({_id:doc._id}).removeOne();
          counter ++
          if( counter % x == 0){
            bulkInsert.execute()
            bulkRemove.execute()
            bulkInsert = db.target.initializeUnorderedBulkOp()
            bulkRemove = db.source.initializeUnorderedBulkOp()
          }
        }
      )
    > bulkInsert.execute()
    > bulkRemove.execute()
    
  2. ==============================

    2.작성된 일괄 작업 @ mahlberg은 마르쿠스-W-보여 주었다 (과 마크 멀린 @ 정제)는 효율적이지만 안전하지. bulkInsert이 실패하면, bulkRemove은 여전히 ​​계속 될 것이다. 당신이 이동하는 모든 레코드를 잃지 말고하려면이 대신 사용 :

    작성된 일괄 작업 @ mahlberg은 마르쿠스-W-보여 주었다 (과 마크 멀린 @ 정제)는 효율적이지만 안전하지. bulkInsert이 실패하면, bulkRemove은 여전히 ​​계속 될 것이다. 당신이 이동하는 모든 레코드를 잃지 말고하려면이 대신 사용 :

    함수 insertBatch (수집 문서) {   VAR bulkInsert collection.initializeUnorderedBulkOp = ();   VAR insertedIds = [];   VAR 아이디;   documents.forEach (함수 (의사) {     식 doc._id;     // 삽입을 중복 오류를 발생시키지 않고     bulkInsert.find (_ {ID : ID}).. upsert () replaceOne (문서);     insertedIds.push (ID);   });   bulkInsert.execute ();   반환 insertedIds; } 함수 deleteBatch (수집 문서) {   VAR bulkRemove collection.initializeUnorderedBulkOp = ();   documents.forEach (함수 (의사) {     bulkRemove.find ({_ ID : doc._id}). removeOne ();   });   bulkRemove.execute (); } 함수 moveDocuments (sourceCollection, targetCollection, 필터 BATCHSIZE) {   인쇄 ( "이동"+ sourceCollection.find (필터) .count () + + + + sourceCollection targetCollection '에서' '문서');   VAR 수;   반면 ((COUNT = sourceCollection.find (필터) .count ())> 0) {     인쇄 (카운트 + "문서가 남아있는");     된 sourcedocs = sourceCollection.find (필터)으로 제한 할 (BATCHSIZE);     idsOfCopiedDocs = insertBatch (targetCollection, 된 sourcedocs);     targetDocs = targetCollection.find (_ {ID :에 {$ : idsOfCopiedDocs}});     deleteBatch (sourceCollection, targetDocs);   }   ( "완료!") 인쇄 }

  3. ==============================

    3.삽입 및 제거 :

    삽입 및 제거 :

    var documentsToMove = db.collectionA.find({});
    documentsToMove.forEach(function(doc) {
        db.collectionB.insert(doc);
        db.collectionA.remove(doc);
    });
    

    참고 :이 방법은 큰 문서를 들고 큰 컬렉션 또는 컬렉션에 매우 느려질 수 있습니다.

  4. ==============================

    4.밖으로 $하여 데이터를 새 컬렉션을 만드는 데 사용하는, 그래서 $를 사용

    밖으로 $하여 데이터를 새 컬렉션을 만드는 데 사용하는, 그래서 $를 사용

    db.oldCollection.aggregate([{$out : "newCollection"}])
    

    다음 놓기를 사용하여

    db.oldCollection.drop()
    
  5. ==============================

    5.이것은 @Markus W Mahlberg의 다시 진술

    이것은 @Markus W Mahlberg의 다시 진술

    호의를 반환 - 함수로

    function moveDocuments(sourceCollection,targetCollection,filter) {
        var bulkInsert = targetCollection.initializeUnorderedBulkOp();
        var bulkRemove = sourceCollection.initializeUnorderedBulkOp();
        sourceCollection.find(filter)
            .forEach(function(doc) {
            bulkInsert.insert(doc);
            bulkRemove.find({_id:doc._id}).removeOne();
            }
      )
      bulkInsert.execute();
      bulkRemove.execute();
    }
    

    예제 사용

    var x = {dsid:{$exists: true}};
    moveDocuments(db.pictures,db.artifacts,x)
    

    유물 컬렉션에 사진에서 최상위 요소 DSID있는 모든 문서를 이동

  6. ==============================

    6.그것은 하나의 명령을 사용하여 (당신이 쿼리 부분에 대한 인덱스가 특히)보다는 그들에게 하나씩을 삭제하는 많은 문서를 제거하는 것이 좋습니다보기의 성능 지점에서 할 수 있습니다.

    그것은 하나의 명령을 사용하여 (당신이 쿼리 부분에 대한 인덱스가 특히)보다는 그들에게 하나씩을 삭제하는 많은 문서를 제거하는 것이 좋습니다보기의 성능 지점에서 할 수 있습니다.

    예를 들면 :

    db.source.find({$gte: start, $lt: end}).forEach(function(doc){
       db.target.insert(doc);
    });
    db.source.remove({$gte: start, $lt: end});
    
  7. ==============================

    7.당신은 sourceCollection에서 데이터를 가져 와서에 변수 및 루프의 커서 데이터를 유지하고 목표 컬렉션에 삽입 할 범위 쿼리를 사용할 수 있습니다 :

    당신은 sourceCollection에서 데이터를 가져 와서에 변수 및 루프의 커서 데이터를 유지하고 목표 컬렉션에 삽입 할 범위 쿼리를 사용할 수 있습니다 :

     var doc = db.sourceCollection.find({
            "Timestamp":{
                  $gte:ISODate("2014-09-01T00:00:00Z"),
                  $lt:ISODate("2014-10-01T00:00:00Z")
            }
     });
    
     doc.forEach(function(doc){
        db.targetCollection.insert(doc);
     })
    

    희망은 그래서 도움이!

  8. ==============================

    8.MongoDB를 3.0까지에서 다음과 같은 구문으로하는 CopyTo 명령을 사용할 수 있습니다 :

    MongoDB를 3.0까지에서 다음과 같은 구문으로하는 CopyTo 명령을 사용할 수 있습니다 :

    db.source_collection.copyTo("target_collection")
    

    그럼 당신은 기존의 수집을 제거하기 위해 드롭 명령을 사용할 수 있습니다 :

    db.source_collection.drop()
    
  9. ==============================

    9.여기 (여기 읽기 문서) 더 최근 몽고 'bulkWrite'작업을 사용 @ jasongarber의 대답에 대한 업데이트는, 그리고 당신이 그 '완성에 따라 넓은 스크립트의 일부로 실행할 수 있도록 또한 전체 프로세스의 비동기를 유지합니다.

    여기 (여기 읽기 문서) 더 최근 몽고 'bulkWrite'작업을 사용 @ jasongarber의 대답에 대한 업데이트는, 그리고 당신이 그 '완성에 따라 넓은 스크립트의 일부로 실행할 수 있도록 또한 전체 프로세스의 비동기를 유지합니다.

    async function moveDocuments (sourceCollection, targetCollection, filter) {
      const sourceDocs = await sourceCollection.find(filter)
    
      console.log(`Moving ${await sourceDocs.count()} documents from ${sourceCollection.collectionName} to ${targetCollection.collectionName}`)
    
      const idsOfCopiedDocs = await insertDocuments(targetCollection, sourceDocs)
    
      const targetDocs = await targetCollection.find({_id: {$in: idsOfCopiedDocs}})
      await deleteDocuments(sourceCollection, targetDocs)
    
      console.log('Done!')
    }
    
    async function insertDocuments (collection, documents) {
      const insertedIds = []
      const bulkWrites = []
    
      await documents.forEach(doc => {
        const {_id} = doc
    
        insertedIds.push(_id)
        bulkWrites.push({
          replaceOne: {
            filter: {_id},
            replacement: doc,
            upsert: true,
          },
        })
      })
    
      if (bulkWrites.length) await collection.bulkWrite(bulkWrites, {ordered: false})
    
      return insertedIds
    }
    
    async function deleteDocuments (collection, documents) {
      const bulkWrites = []
    
      await documents.forEach(({_id}) => {
        bulkWrites.push({
          deleteOne: {
            filter: {_id},
          },
        })
      })
    
      if (bulkWrites.length) await collection.bulkWrite(bulkWrites, {ordered: false})
    }
    
  10. ==============================

    10.그러나 나는 시간에, 나는 사람들을 위해 조금 간단하게 유지해야 할 필요성을 보았다, @ 마르쿠스-w-mahlberg의 응답 좋아한다. 따라서 저는 다음과 같습니다 기능의 몇 가지있다. 그가했던 것처럼 자연스럽게 대량 사업자 여기 일을 포장 할 수 있지만,이 코드는 동일하게 신규 및 기존 몽고 시스템과 함께 작동합니다.

    그러나 나는 시간에, 나는 사람들을 위해 조금 간단하게 유지해야 할 필요성을 보았다, @ 마르쿠스-w-mahlberg의 응답 좋아한다. 따라서 저는 다음과 같습니다 기능의 몇 가지있다. 그가했던 것처럼 자연스럽게 대량 사업자 여기 일을 포장 할 수 있지만,이 코드는 동일하게 신규 및 기존 몽고 시스템과 함께 작동합니다.

    function parseNS(ns){
        //Expects we are forcing people to not violate the rules and not doing "foodb.foocollection.month.day.year" if they do they need to use an array.
        if (ns instanceof Array){
            database =  ns[0];
            collection = ns[1];
        }
        else{
            tNS =  ns.split(".");
            if (tNS.length > 2){
                print('ERROR: NS had more than 1 period in it, please pass as an [ "dbname","coll.name.with.dots"] !');
                return false;
            }
            database = tNS[0];
            collection = tNS[1];
        }
        return {database: database,collection: collection};
    }
    
    function insertFromCollection( sourceNS,  destNS, query, batchSize, pauseMS){
        //Parse and check namespaces
        srcNS = parseNS(sourceNS);
        destNS = parseNS(destNS);
        if ( srcNS == false ||  destNS == false){return false;}
    
        batchBucket = new Array();
        totalToProcess = db.getDB(srcNS.database).getCollection(srcNS.collection).find(query,{_id:1}).count();
        currentCount = 0;
        print("Processed "+currentCount+"/"+totalToProcess+"...");
        db.getDB(srcNS.database).getCollection(srcNS.collection).find(query).addOption(DBQuery.Option.noTimeout).forEach(function(doc){
            batchBucket.push(doc);
            if ( batchBucket.length > batchSize){
                db.getDB(destNS.database).getCollection(destNS.collection)insert(batchBucket);
                currentCount += batchBucket.length;
                batchBucket = [];
                sleep (pauseMS);
                print("Processed "+currentCount+"/"+totalToProcess+"...");       
            }
        }
        print("Completed");
    }
    
    /** Example Usage:
            insertFromCollection("foo.bar","foo2.bar",{"type":"archive"},1000,20);    
    

    당신은 분명히 db.getSiblingDB (srcNS.database) .getCollection (srcNS.collection) .remove 추가 할 수 있습니다 (쿼리, 참) 경우에 당신은 그들이 새 위치로 복사 한 후 또한 레코드를 제거하고 싶었다. 코드는 쉽게 다시 시작할 수 있도록 그렇게 만들 수 있습니다.

  11. ==============================

    11.나는 대량 삽입 및 pymongo의 대량 삭제 방법을 사용하여 한 번에 1000 개 개의 레코드를 arhieve 할 계획.

    나는 대량 삽입 및 pymongo의 대량 삭제 방법을 사용하여 한 번에 1000 개 개의 레코드를 arhieve 할 계획.

    소스 및 대상 모두

  12. ==============================

    12.나는 문서 15 만 달러에 2,297 수집을했지만, 일부 콜렉션은 비어 있었다.

    나는 문서 15 만 달러에 2,297 수집을했지만, 일부 콜렉션은 비어 있었다.

    스크립트는하지만,이 스크립트 최적화, 실패 만하는 CopyTo 사용 :

    db.getCollectionNames().forEach(function(collname) {
        var c = db.getCollection(collname).count();
        if(c!==0){
          db.getCollection(collname).copyTo('master-collection');
          print('Copied collection ' + collname);
        }
    });
    

    모두 나를 위해 잘 작동합니다.

    주의 :이 읽기 / 쓰기 작업을 차단하기 때문에 사항 copyTo가되지 않습니다 : 나는 당신이 데이터베이스가이 작업을 수행하는 동안 사용할 수없는 것을 알고있는 경우에 좋은 생각 때문에.

  13. from https://stackoverflow.com/questions/27039083/mongodb-move-documents-from-one-collection-to-another-collection by cc-by-sa and MIT license