[MONGODB] 다른 컬렉션에 하나 개의 컬렉션에서 MongoDB를 이동 문서
MONGODB다른 컬렉션에 하나 개의 컬렉션에서 MongoDB를 이동 문서
어떻게 문서는 MongoDB의 다른 컬렉션에 하나 개의 컬렉션 이동할 수 있습니다 ?? 예를 들면 : 나는 수집 A의 문서를 많이하고 난 (이 1개월 오래된 문서를 수집 (A)에 안) 수집 B에 대한 모든 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.작성된 일괄 작업 @ 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.삽입 및 제거 :
삽입 및 제거 :
var documentsToMove = db.collectionA.find({}); documentsToMove.forEach(function(doc) { db.collectionB.insert(doc); db.collectionA.remove(doc); });
참고 :이 방법은 큰 문서를 들고 큰 컬렉션 또는 컬렉션에 매우 느려질 수 있습니다.
-
==============================
4.밖으로 $하여 데이터를 새 컬렉션을 만드는 데 사용하는, 그래서 $를 사용
밖으로 $하여 데이터를 새 컬렉션을 만드는 데 사용하는, 그래서 $를 사용
db.oldCollection.aggregate([{$out : "newCollection"}])
다음 놓기를 사용하여
db.oldCollection.drop()
-
==============================
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.그것은 하나의 명령을 사용하여 (당신이 쿼리 부분에 대한 인덱스가 특히)보다는 그들에게 하나씩을 삭제하는 많은 문서를 제거하는 것이 좋습니다보기의 성능 지점에서 할 수 있습니다.
그것은 하나의 명령을 사용하여 (당신이 쿼리 부분에 대한 인덱스가 특히)보다는 그들에게 하나씩을 삭제하는 많은 문서를 제거하는 것이 좋습니다보기의 성능 지점에서 할 수 있습니다.
예를 들면 :
db.source.find({$gte: start, $lt: end}).forEach(function(doc){ db.target.insert(doc); }); db.source.remove({$gte: start, $lt: end});
-
==============================
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.MongoDB를 3.0까지에서 다음과 같은 구문으로하는 CopyTo 명령을 사용할 수 있습니다 :
MongoDB를 3.0까지에서 다음과 같은 구문으로하는 CopyTo 명령을 사용할 수 있습니다 :
db.source_collection.copyTo("target_collection")
그럼 당신은 기존의 수집을 제거하기 위해 드롭 명령을 사용할 수 있습니다 :
db.source_collection.drop()
-
==============================
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.그러나 나는 시간에, 나는 사람들을 위해 조금 간단하게 유지해야 할 필요성을 보았다, @ 마르쿠스-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.나는 대량 삽입 및 pymongo의 대량 삭제 방법을 사용하여 한 번에 1000 개 개의 레코드를 arhieve 할 계획.
나는 대량 삽입 및 pymongo의 대량 삭제 방법을 사용하여 한 번에 1000 개 개의 레코드를 arhieve 할 계획.
소스 및 대상 모두
-
==============================
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가되지 않습니다 : 나는 당신이 데이터베이스가이 작업을 수행하는 동안 사용할 수없는 것을 알고있는 경우에 좋은 생각 때문에.
from https://stackoverflow.com/questions/27039083/mongodb-move-documents-from-one-collection-to-another-collection by cc-by-sa and MIT license
'MONGODB' 카테고리의 다른 글
[MONGODB] 몽고에서 샤딩 및 복제의 차이점은 무엇입니까? (0) | 2019.12.21 |
---|---|
[MONGODB] 같은 MongoDB의 쿼리 수와 고유 한 카운트에서 그룹을 선택합니다 (0) | 2019.12.21 |
[MONGODB] $ 생략하고 통합 프레임 워크에서 $ 한계 (0) | 2019.12.21 |
[MONGODB] MongoDB의에서 컬렉션을 복제 (0) | 2019.12.21 |
[MONGODB] MongoDB를 작동하지 않습니다. "ERROR : DBPATH (/ 데이터 / DB)가 존재하지 않습니다." (0) | 2019.12.21 |