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.key
PHP 코드를 작성하여 각 레코드를 트래버스하고 레코드가 있으면 제거하려고 생각하고 있습니다.
Mongo Internal 명령줄에서 중복을 제거할 수 있는 방법이 있습니까?
이 답변은 더 이상 사용되지 않습니다.그자리의 dropDups
MongoDB 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보다 크면 삭제합니다.
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
- 모든 언어로 스크립트 생성
- 당신의 수집품을 반복합니다.
- 새 컬렉션을 만들고 이 컬렉션에서 고유한 true로 설정된 새 인덱스를 만듭니다. 이 인덱스는 원래 컬렉션에서 중복된 이름을 제거하려는 인덱스와 같아야 합니다. ex-u는 컬렉션 게임을 가지고 있으며, 이 컬렉션에서는 제거하려는 중복된 필드 장르가 있습니다.따라서 새 컬렉션 db.createCollection("cname")을 생성하면 됩니다. 새 인덱스 db.cname.create인덱스({'gener':1), 고유:1)에서 유사한 장르의 문서만 먼저 삽입할 때 다른 문서는 중복 키 오류와 함께 거부됩니다.
- 이제 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
'programing' 카테고리의 다른 글
모든 테이블 이름을 나열하는 PostgreSQL 쿼리? (0) | 2023.05.16 |
---|---|
Git의 분기에서 변경 사항을 가져오는 방법 (0) | 2023.05.11 |
보호하다.리버스 엔지니어링의 NET 코드? (0) | 2023.05.11 |
기존 Git 분기 추적을 원격 분기로 설정하시겠습니까? (0) | 2023.05.11 |
두 개의 IEnumberable을 새로운 IEnumberable로 연결하는 방법은 무엇입니까? (0) | 2023.05.11 |