Jak usunąć duplikaty na podstawie klucza w Mongodb?
Mam kolekcję w MongoDB, gdzie jest około (~3 miliony płyt). Mój przykładowy zapis wyglądałby tak:
{ "_id" = ObjectId("50731xxxxxxxxxxxxxxxxxxxx"),
"source_references" : [
"_id" : ObjectId("5045xxxxxxxxxxxxxx"),
"name" : "xxx",
"key" : 123
]
}
Mam wiele zduplikowanych rekordów w kolekcji o tym samym source_references.key
. (Przez duplikat mam na myśli source_references.key
nie _id
).
Chcę usunąć zduplikowane rekordy na podstawie source_references.key
, myślę o napisaniu kodu PHP, aby przejść każdy rekord i usunąć rekord, jeśli istnieje.
Czy istnieje sposób na usunięcie duplikatów w wewnętrznej komendzie Mongo linia?
7 answers
Jeśli jesteś pewien, że source_references.key
identyfikuje zduplikowane rekordy, możesz zapewnić unikalny Indeks z dropDups:true
opcja tworzenia indeksu w MongoDB 2.6 lub starszym:
db.things.ensureIndex({'source_references.key' : 1}, {unique : true, dropDups : true})
Spowoduje to zachowanie pierwszego unikalnego dokumentu dla każdej wartości source_references.key
i usunięcie kolejnych dokumentów, które w przeciwnym razie spowodowałyby złamanie duplikatu klucza.
Ważne Uwagi :
- opcja
dropDups
została usunięta W MongoDB 3.0 , więc inne podejście będzie wymagane. Na przykład, możesz użyć agregacji zgodnie z sugestią na: MongoDB duplicate documents nawet po dodaniu unikalnego klucza . - wszelkie dokumenty, w których brakuje pola
source_references.key
, będą traktowane jako posiadające wartość null , więc kolejne dokumenty, w których brakuje pola klucza, zostaną usunięte. Możesz dodaćsparse:true
opcja tworzenia indeksu, więc indeks ma zastosowanie tylko do dokumentów z polemsource_references.key
.
Oczywista Uwaga : zrób kopię zapasową swojego jeśli obawiasz się niezamierzonej utraty danych, spróbuj najpierw w środowisku przejściowym.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:35
Jest to najprostsze zapytanie, którego użyłem na moim MongoDB 3.2
db.myCollection.find({}, {myCustomKey:1}).sort({_id:1}).forEach(function(doc){
db.myCollection.remove({_id:{$gt:doc._id}, myCustomKey:doc.myCustomKey});
})
Zindeksuj swój customKey
przed uruchomieniem, aby zwiększyć prędkość
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-19 07:44:40
Usuń duplikaty przez framework agregacji .
A. Jeśli chcesz usunąć za jednym razem.
var duplicates = [];
db.collectionName.aggregate([
// discard selection criteria, You can remove "$match" section if you want
{ $match: {
source_references.key: { "$ne": '' }
}},
{ $group: {
_id: { source_references.key: "$source_references.key"}, // can be grouped on multiple properties
dups: { "$addToSet": "$_id" },
count: { "$sum": 1 }
}},
{ $match: {
count: { "$gt": 1 } // Duplicates considered as count greater than one
}}
]) // You can display result until this and check duplicates
.forEach(function(doc) {
doc.dups.shift(); // First element skipped for deleting
doc.dups.forEach( function(dupId){
duplicates.push(dupId); // Getting all duplicate ids
}
)
})
// If you want to Check all "_id" which you are deleting else print statement not needed
printjson(duplicates);
// Remove all duplicates in one go
db.collectionName.remove({_id:{$in:duplicates}})
B. możesz usuwać dokumenty jeden po drugim.
db.collectionName.aggregate([
// discard selection criteria, You can remove "$match" section if you want
{ $match: {
source_references.key: { "$ne": '' }
}},
{ $group: {
_id: { source_references.key: "$source_references.key"}, // can be grouped on multiple properties
dups: { "$addToSet": "$_id" },
count: { "$sum": 1 }
}},
{ $match: {
count: { "$gt": 1 } // Duplicates considered as count greater than one
}}
]) // You can display result until this and check duplicates
.forEach(function(doc) {
doc.dups.shift(); // First element skipped for deleting
db.collectionName.remove({_id : {$in: doc.dups }}); // Delete remaining duplicates
})
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-12 06:44:39
Podczas gdy @Stennie ' S jest poprawną odpowiedzią, nie jest to jedyny sposób. W rzeczywistości Podręcznik MongoDB prosi, abyś był bardzo ostrożny podczas robienia tego. Istnieją dwie inne opcje
- niech MongoDB zrobi to za Ciebie używając Map Reduce
- robisz programowo co jest mniej efektywne.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:15
Oto nieco bardziej "ręczny" sposób na zrobienie tego:
Zasadniczo najpierw uzyskaj listę wszystkich unikalnych kluczy, które Cię interesują.
Następnie wykonaj wyszukiwanie za pomocą każdego z tych klawiszy i usuń, jeśli wyszukiwanie zwróci większe niż jeden.
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++
})
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-23 12:51:15
Pip install mongo_remove_duplicate_indexes
- tworzenie skryptu w dowolnym języku
- iteruj nad swoją kolekcją
- Utwórz nową kolekcję i utwórz nowy indeks w tej kolekcji z unikalnym ustawieniem na true, pamiętaj ten indeks musi być taki sam jak indeks U chcesz usunąć duplikaty z oryginalnej kolekcji o tej samej nazwie dla ex-u mają kolekcję gier, a w tej kolekcji u mają pole gatunek, który zawiera duplikaty, które u chcą usunąć, więc po prostu utworzyć nowy kolekcja db.createCollection ("cname") utwórz nowy indeks db.cname.createIndex({'genre':1}, unikalnych:1) teraz, gdy u wstawi dokument o podobnym gatunku, tylko pierwszy zostanie zaakceptowany, inny zostanie odrzucony z błędem klucza duplicae
- Teraz wystarczy wstawić wartości formatu json u otrzymane do nowej kolekcji i obsłużyć wyjątek za pomocą obsługi wyjątków dla ex pymongo.błędy.DuplicateKeyError
Sprawdź kod źródłowy pakietu dla mongo_remove_duplicate_indexes dla lepszego zrozumienie
Jeśli masz wystarczająco dużo pamięci, możesz w Scali zrobić coś takiego:
cole.find().groupBy(_.customField).filter(_._2.size>1).map(_._2.tail).flatten.map(_.id)
.foreach(x=>cole.remove({id $eq x})
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-12 16:22:10