programing

Mongodb에서 키를 기반으로 중복을 제거하는 방법은 무엇입니까?

abcjava 2023. 5. 11. 21:03
반응형

Mongodb에서 키를 기반으로 중복을 제거하는 방법은 무엇입니까?

저는 MongoDB에 약 (~300만 개의 레코드) 정도의 컬렉션을 가지고 있습니다.제 샘플 기록은 다음과 같습니다.

 { "_id" = ObjectId("50731xxxxxxxxxxxxxxxxxxxx"),
   "source_references" : [
                           "_id" : ObjectId("5045xxxxxxxxxxxxxx"),
                           "name" : "xxx",
                           "key" : 123
                          ]
 }

컬렉션에 중복된 레코드가 많이 있습니다. 같은 레코드가 있습니다.source_references.key 내 말은, (Duplicate 내은말,은말),source_references.key이 아닌_id).

다음을 기준으로 중복된 레코드를 제거합니다.source_references.keyPHP 코드를 작성하여 각 레코드를 트래버스하고 레코드가 있으면 제거하려고 생각하고 있습니다.

Mongo Internal 명령줄에서 중복을 제거할 수 있는 방법이 있습니까?

이 답변은 더 이상 사용되지 않습니다.그자리의 dropDupsMongoDB 3.0에서는 옵션이 제거되었으므로 대부분의 경우 다른 접근 방식이 필요합니다.예를 들어, MongoDB는 고유한 키를 추가한 후에도 문서를 복제합니다.

만약 당신이 확신한다면,source_references.key중복 레코드를 식별합니다. MongoDB 2.6 이상의 인덱스 생성 옵션을 사용하여 고유한 인덱스를 확인할 수 있습니다.

db.things.ensureIndex({'source_references.key' : 1}, {unique : true, dropDups : true})

각 에 대한 첫 번째 고유 문서가 됩니다.source_references.key값을 지정하고, 중복 키 위반을 유발할 수 있는 후속 문서를 삭제합니다.

중요 참고:누락된 모든 문서source_references.key필드는 null 값을 가진 것으로 간주되므로 키 필드가 없는 후속 문서는 삭제됩니다.색인이 다음 문서에만 적용되도록 색인 작성 선택사항을 추가할 수 있습니다.source_references.key밭.밭.

명백한 주의:데이터베이스를 백업하고 의도하지 않은 데이터 손실이 우려되는 경우 먼저 준비 환경에서 백업을 시도합니다.

이것은 MongoDB 3.2에서 사용한 가장 쉬운 쿼리입니다.

db.myCollection.find({}, {myCustomKey:1}).sort({_id:1}).forEach(function(doc){
    db.myCollection.remove({_id:{$gt:doc._id}, myCustomKey:doc.myCustomKey});
})

customKey를 높이기 하기 전에.

@Stennie의 대답은 타당하지만, 그것이 유일한 방법은 아닙니다.실제로 MongoDB 매뉴얼에서는 이 작업을 수행하는 동안 매우 주의해야 한다고 요청합니다.다른 두 가지 옵션이 있습니다.

  1. MongoDB가 Map Reduct를 사용하여 이 작업을 수행하도록 합니다.
  2. 당신은 덜 효율적인 프로그램을 실행합니다.

다음은 조금 더 '수동적'인 방법입니다.

기본적으로 먼저 관심 있는 모든 고유 키 목록을 가져옵니다.

그런 다음 각 키를 사용하여 검색을 수행하고 검색 결과가 1보다 크면 삭제합니다.

    db.collection.distinct("key").forEach((num)=>{
      var i = 0;
      db.collection.find({key: num}).forEach((doc)=>{
        if (i)   db.collection.remove({key: num}, { justOne: true })
        i++
      })
    });

저도 비슷한 요구사항이 있었지만, 최신 엔트리를 유지하고 싶었습니다.다음 쿼리는 수백만 개의 레코드와 복제품이 있는 제 컬렉션에서 작동했습니다.

/** Create a array to store all duplicate records ids*/
var duplicates = [];

/** Start Aggregation pipeline*/
db.collection.aggregate([
  {
    $match: { /** Add any filter here. Add index for filter keys*/
      filterKey: {
        $exists: false
      }
    }
  },
  {
    $sort: { /** Sort it in such a way that you want to retain first element*/
      createdAt: -1
    }
  },
  {
    $group: {
      _id: {
        key1: "$key1", key2:"$key2" /** These are the keys which define the duplicate. Here document with same value for key1 and key2 will be considered duplicate*/
      },
      dups: {
        $push: {
          _id: "$_id"
        }
      },
      count: {
        $sum: 1
      }
    }
  },
  {
    $match: {
      count: {
        "$gt": 1
      }
    }
  }
],
{
  allowDiskUse: true
}).forEach(function(doc){
  doc.dups.shift();
  doc.dups.forEach(function(dupId){
    duplicates.push(dupId._id);
  })
})

/** Delete the duplicates*/
var i,j,temparray,chunk = 100000;
for (i=0,j=duplicates.length; i<j; i+=chunk) {
    temparray = duplicates.slice(i,i+chunk);
    db.collection.bulkWrite([{deleteMany:{"filter":{"_id":{"$in":temparray}}}}])
}

페르난도의 답변을 확장해보니 시간이 너무 오래 걸리는 것 같아서 수정했습니다.

var x = 0;
db.collection.distinct("field").forEach(fieldValue => {
  var i = 0;
  db.collection.find({ "field": fieldValue }).forEach(doc => {
    if (i) {
      db.collection.remove({ _id: doc._id });
    }
    i++;
    x += 1;
    if (x % 100 === 0) {
      print(x); // Every time we process 100 docs.
    }
  });
});

개선 사항은 기본적으로 문서 ID를 사용하여 제거하는 것으로, 더 빨라야 하며 작업 진행률을 추가하면 반복 값을 원하는 양으로 변경할 수 있습니다.

또한 작업 전에 필드를 인덱싱하면 도움이 됩니다.

pip 설치 mongo_remove_message_message

  1. 모든 언어로 스크립트 생성
  2. 당신의 수집품을 반복합니다.
  3. 새 컬렉션을 만들고 이 컬렉션에서 고유한 true로 설정된 새 인덱스를 만듭니다. 이 인덱스는 원래 컬렉션에서 중복된 이름을 제거하려는 인덱스와 같아야 합니다. ex-u는 컬렉션 게임을 가지고 있으며, 이 컬렉션에서는 제거하려는 중복된 필드 장르가 있습니다.따라서 새 컬렉션 db.createCollection("cname")을 생성하면 됩니다. 새 인덱스 db.cname.create인덱스({'gener':1), 고유:1)에서 유사한 장르의 문서만 먼저 삽입할 때 다른 문서는 중복 키 오류와 함께 거부됩니다.
  4. 이제 expmongo.dll에 대한 예외 처리를 사용하여 수신한 json 형식 값을 새 컬렉션에 삽입하고 예외를 처리합니다.중복 키 오류

mongo_remove_module_dll 패키지 소스 코드를 확인하여 더 잘 이해할 수 있도록 합니다.

메모리가 충분하면 스칼라에서 다음과 같은 작업을 수행할 수 있습니다.

cole.find().groupBy(_.customField).filter(_._2.size>1).map(_._2.tail).flatten.map(_.id)
.foreach(x=>cole.remove({id $eq x})

언급URL : https://stackoverflow.com/questions/13190370/how-to-remove-duplicates-based-on-a-key-in-mongodb

반응형