Znajdź zduplikowane rekordy w MongoDB


116

Jak znaleźć zduplikowane pola w kolekcji Mongo.

Chciałbym sprawdzić, czy którekolwiek z pól „nazwa” jest duplikatem.

{
    "name" : "ksqn291",
    "__v" : 0,
    "_id" : ObjectId("540f346c3e7fc1054ffa7086"),
    "channel" : "Sales"
}

Wielkie dzięki!


5
Duplikat flagi dla tego pytania jest niezasłużony. To pytanie dotyczy tego, jak znaleźć zduplikowane rekordy, a nie zapobiegać im.
Harry King

Odpowiedzi:


210

Włącz agregację namei korzystaj namez count > 1:

db.collection.aggregate(
    {"$group" : { "_id": "$name", "count": { "$sum": 1 } } },
    {"$match": {"_id" :{ "$ne" : null } , "count" : {"$gt": 1} } }, 
    {"$project": {"name" : "$_id", "_id" : 0} }
)

Aby posortować wyniki według największej lub najmniejszej liczby duplikatów:

db.collection.aggregate(
    {"$group" : { "_id": "$name", "count": { "$sum": 1 } } },
    {"$match": {"_id" :{ "$ne" : null } , "count" : {"$gt": 1} } }, 
    {"$sort": {"count" : -1} },
    {"$project": {"name" : "$_id", "_id" : 0} }     
)

Aby użyć innej nazwy kolumny niż „name”, zmień „ $ name ” na „ $ column_name


1
"$match": {"_id" :{ "$ne" : null } - jest tu zbędna, gdyż druga część instrukcji wystarczyłaby do przefiltrowania wyniku. Więc wystarczy tylko sprawdzenie, czy grupa ma count > 1.
BatScream

5
Tks @BatScream. {"$ ne": null} istnieje na wypadek, gdyby 'nazwa' była pusta lub nie istniała. Agregacja również liczy się jako zero.
anhlc

1
Witamy. Ale w takim razie po co sprawdzać to _idpole. Zawsze gwarantuje się, że po groupoperacji nie będzie zerowa .
BatScream

4
_idDokumentu ze $groupsceny może być null.
wdberkeley

1
Jaki będzie tego wynik? Jeśli uruchomię, otrzymam wszystkie dokumenty, których potrzebuję, to chcę tylko zduplikowane identyfikatory / nazwy.
Kannan T

24

Można znaleźć listw duplicatenazwach stosując następujące aggregaterurociągu:

  • Groupwszystkie rekordy mają podobne name.
  • Matchtych groups, którzy mają rekordy większe niż 1.
  • Następnie groupponownie do projectwszystkich zduplikowanych nazw jako pliku array.

Kod:

db.collection.aggregate([
{$group:{"_id":"$name","name":{$first:"$name"},"count":{$sum:1}}},
{$match:{"count":{$gt:1}}},
{$project:{"name":1,"_id":0}},
{$group:{"_id":null,"duplicateNames":{$push:"$name"}}},
{$project:{"_id":0,"duplicateNames":1}}
])

o / p:

{ "duplicateNames" : [ "ksqn291", "ksqn29123213Test" ] }

10

Odpowiedź udzielona przez anhic może być bardzo nieefektywna, jeśli masz dużą bazę danych, a nazwa atrybutu jest obecna tylko w niektórych dokumentach.

Aby zwiększyć wydajność, możesz dodać dopasowanie $ do agregacji.

db.collection.aggregate(
    {"$match": {"name" :{ "$ne" : null } } }, 
    {"$group" : {"_id": "$name", "count": { "$sum": 1 } } },
    {"$match": {"count" : {"$gt": 1} } }, 
    {"$project": {"name" : "$_id", "_id" : 0} }
)

3
db.getCollection('orders').aggregate([  
    {$group: { 
            _id: {name: "$name"},
            uniqueIds: {$addToSet: "$_id"},
            count: {$sum: 1}
        } 
    },
    {$match: { 
        count: {"$gt": 1}
        }
    }
])

Pierwsza grupa Zapytaj grupę według pól.

Następnie sprawdzamy unikalny identyfikator i liczymy go, jeśli liczba jest większa niż 1, to pole jest zduplikowane w całej kolekcji, więc to ma być obsługiwane przez zapytanie $ match.


1
nie byłem w stanie sprawić, by ten działał również dla mnie. Głosowanie przeciw!
Mathieu G

Ten post jest stary, ale może komuś pomóc. sprawdź to sprawdzę w moim lokalnym, działa. Nawet ja trafiłem na jeden blog dotyczący tego. Proszę spojrzeć. compose.com/articles/finding-duplicate-documents-in-mongodb
Aman shrivastava

Udało mi się to uruchomić - edytowane, aby zaktualizować do potwierdzonej wersji roboczej.
AL Strine
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.