복붙노트

[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. ==============================

    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. ==============================

    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. ==============================

    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. ==============================

    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/

  5. from https://stackoverflow.com/questions/8405331/how-to-remove-duplicate-record-in-mongodb-by-mapreduce by cc-by-sa and MIT license