[MONGODB] 어떻게 맵리 듀스로 MongoDB를 중복 레코드를 제거하려면?
MONGODB어떻게 맵리 듀스로 MongoDB를 중복 레코드를 제거하려면?
나는 MongoDB를에 매우 큰 컬렉션을하고 난 그 컬렉션에서 중복 레코드를 제거하고자합니다. 내 마음이 인덱스를 삭제하고 dropDups와 인덱스를 재구성하는 것입니다 먼저 생각 온다. 그러나, 중복 된 데이터는 MongoDB를 처리 할 너무 많은 것입니다.
그래서 도움을 맵리 듀스로 변합니다. 여기 내 현재 진행 상황입니다.
m = function () {
emit(this.myid, 1);
}
r = function (k, vals) {
return Array.sum(vals);
}
res = db.userList.mapReduce(m,r, { out : "myoutput" });
그리고 모든 중복 레코드의 "대한 myid"는 "myoutput '컬렉션에 저장됩니다. 그러나, 나는 myoutput.myid를 참조하여 userList 여기서에서 레코드를 제거하는 방법을 모르겠어요. 그것은이 같은 것으로 가정한다 :
db.myoutput.find({value: {$gt: 1}}).forEach(
function(obj) {
db.userList.remove(xxxxxxxxx) // I don't know how to do so
})
BTW, foreach 문을 사용하면 제정신에 대한 myid 모든 기록을 닦아 주실 것이다 보인다. 하지만 난 그냥 중복 레코드를 제거합니다. 전의:
{ "_id" : ObjectId("4edc6773e206a55d1c0000d8"), "myid" : 0 }
{ "_id" : ObjectId("4edc6780e206a55e6100011a"), "myid" : 0 }
{ "_id" : ObjectId("4edc6784e206a55ed30000c1"), "myid" : 0 }
최종 결과는 하나의 기록을 보존해야한다. 누군가가 나에게 이것에 어떤 도움을 줄 수 있습니까?
감사합니다. :)
해결법
-
==============================
1.깨끗한 레코드를 삭제하는 클라이언트 측 스크립트를 작성하는 아마 :
깨끗한 레코드를 삭제하는 클라이언트 측 스크립트를 작성하는 아마 :
db.myoutput.find({value: {$gt: 1}}).forEach( function(obj) { var cur = db.userList.find({ myid: obj._id }, {_id: 1}); var first = true; while (cur.hasNext()) { var doc = cur.next(); if (first) {first = false; continue;} db.userList.remove({ _id: doc._id }); } })
자극 데이터에 대해 실행하는 경우 그래서 항상 한 번 확인을이 코드를 테스트하지 않았습니다 ..
-
==============================
2.위의 대답은 매우 효과적이지만 당신이 당신의 데이터베이스 / 컬렉션 900K 또는 3M 기록이있는 경우, 그것은 매우 느린 참이다.
위의 대답은 매우 효과적이지만 당신이 당신의 데이터베이스 / 컬렉션 900K 또는 3M 기록이있는 경우, 그것은 매우 느린 참이다.
많은 양의 데이터를 다루는 경우에, 나는 긴 길을 복용하는 것이 좋습니다 :
900K 항목의 경우,이 35S (그룹 쿼리) 주위했다.
PHP에서 구현 :
$mongo_client = new MongoClient(); $collection = $mongo_client->selectCollection("main", "settings"); //Group by the field "code" $keys = array("code" => 1); //You must create objects for every field you wish to transfer (except the one grouped by - that gets auto-transferred) $initial = array("location" => "", "name" => "", "score" => 0, "type" => ""); //The reduce function will set the grouped properties $reduce = "function (obj, prev) { prev.location = obj.location; prev.name = obj.name; prev.score = obj.score; prev.type = obj.type; }"; $fh = fopen("Export.json", "w"); $unique_set = $collection->group($keys, $initial, $reduce); fwrite($fh, json_encode($unique_set['retval'])); fclose($fh);
당신은 거의 중복이있는 경우, PHP에 그것을 실행하는 최선의 선택되지 않을 수도 있습니다,하지만 내 세트는 최종 데이터 세트가 쉽게 처리 할 수 있었다, 그래서 중복의 거대한 숫자를했다. 아마도 누군가가 속도에 대한이 유용 할 것이다. (그리고 몽고 쉘에 전달하는 것은 쉬운 공정해야한다.)
당신이 다시 형식으로 mongoimport와 작업에 대한 한 줄에 한 문서를 가지고 최종 파일이있을 것이다, 그러나 기억하십시오. (A 검색 / 모두가 여기에 괜찮을 대체합니다.)
-
==============================
3.실제로 여기 맵리 듀스 필요가 없다. 이것에 대해 무엇? 몽고 쉘 코드를 붙여 넣습니다 :
실제로 여기 맵리 듀스 필요가 없다. 이것에 대해 무엇? 몽고 쉘 코드를 붙여 넣습니다 :
function removeDupls (collectionName, keyField, reportEvery) { if (reportEvery === undefined) {reportEvery=10;} sort = {}; sort[keyField] = 1; var myidLast; var res = {docsCnt:0,docsRemoved:0} db[collectionName].find().sort(sort).clone().forEach( function(doc) { res['docsCnt'] += 1; if (doc.myid == myidLast) {db[collectionName].remove({_id:doc._id}); res['docsRemoved'] +=1;} else {myidLast = doc.myid;} if (res['docsCnt'] % reportEvery === 0) {print (JSON.stringify(res))} } ); return res; }
다음 전화 :
removeDupls('users','myid',1000)
이 작업을하고 아마 빨리 어떤 맵리 듀스> 제거 작업보다 더 될 것입니다 (중복 문서의 당신의 양에 따라 다름) 당신이 정말 빨리 당신이 문서의 _ids을 저장해야합니다 확인하려면 다음 일괄 제거를 사용하여 임시 배열에서 제거 될 수 있습니다.
-
==============================
4.
/* * This map reduce will output a new collection: "duplicateinvoices" * { "_id" : "12345", "value" : 2 } * { "_id" : "23456", "value" : 2 } * ... **/ m = function () { emit(this.MlsId, 1); } r = function (k, vals) { return Array.sum(vals); } res = db.invoices.mapReduce(m,r, { out : "duplicateinvoices" }); /* * We have two approaches (we should test wich is faster/reliable, i didn't **/ /* OPTION 1 */ // We iterate over duplicateinvoices and get the media-hash // of the ones with value > 1 the duplicates db.duplicateinvoices.find({value: {$gt: 1}}).forEach( function(invoice) { // temporary save one of this objects into a variable var obj = db.invoices.findOne({ media_hash: invoice._id }); // remove all media-hash matched invoices from invoice collection db.invoices.remove({media_hash: invoice._id}) // insert again the previously saved object into collection db.invoices.insert(obj) } ) /* OPTION 2 */ // We iterate over duplicateinvoices and get the media-hash // of the ones with value > 1 the duplicates db.duplicateinvoices.find({value: {$gt: 1}}).forEach( function(invoice) { // Invoices cursor with all the media_hash matched documents var cur = db.invoices.find({ media_hash: invoice._id }); var first = true; while (cur.hasNext()) { var doc = cur.next(); // Skip the first one if (first) {first = false; continue;} // Delete the others matched documents db.userList.remove({ _id: doc._id }); } } )
출처 :
어떻게 맵리 듀스로 MongoDB를 중복 레코드를 제거하려면? http://openmymind.net/2011/1/20/Understanding-Map-Reduce/ http://docs.mongodb.org/manual/tutorial/map-reduce-examples/
from https://stackoverflow.com/questions/8405331/how-to-remove-duplicate-record-in-mongodb-by-mapreduce by cc-by-sa and MIT license
'MONGODB' 카테고리의 다른 글
[MONGODB] 기존 컬렉션에 새 검사기를 추가 (0) | 2019.12.25 |
---|---|
[MONGODB] MongoDB의에서 저장된 함수를 호출 (0) | 2019.12.25 |
[MONGODB] 가장 좋은 방법은 Node.js를를 사용하여 MongoDB에 연결하려면 [중복] (0) | 2019.12.25 |
[MONGODB] 어떻게 유성은 MongoDB를 즉시 변경 알 수 있을까? (0) | 2019.12.25 |
[MONGODB] 배열에 배열에서 항목을 업데이트 (0) | 2019.12.24 |