Suchen Sie doppelte Datensätze in MongoDB

116

Wie würde ich doppelte Felder in einer Mongo-Sammlung finden?

Ich möchte überprüfen, ob eines der "Namens" -Felder Duplikate sind.

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

Danke vielmals!

Chris
quelle
5
Das doppelte Flag für diese Frage ist unverdient. In dieser Frage wird gefragt, wie doppelte Datensätze gefunden und nicht verhindert werden sollen.
Harry King

Antworten:

209

Verwenden Sie die Aggregation für nameund erhalten Sie namemit count > 1:

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

So sortieren Sie die Ergebnisse nach den meisten bis zu den wenigsten Duplikaten:

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

Ändern Sie " $ name " in " $ column_name ", um es mit einem anderen Spaltennamen als "name " zu verwenden.

anhlc
quelle
1
"$match": {"_id" :{ "$ne" : null } - ist hier nicht erforderlich, da der zweite Teil der Anweisung ausreichen würde, um das Ergebnis zu filtern. Es reicht also aus, nur nach der Gruppe zu suchen count > 1, die sie hat.
BatScream
5
Tks @BatScream. {"$ ne": null} gibt es nur für den Fall, dass 'name' null ist oder nicht existiert. Die Aggregation zählt ebenfalls null.
Anhlc
1
Herzlich willkommen. Aber warum dann das _idFeld überprüfen . Es ist immer garantiert, dass es nach der groupOperation nicht null ist .
BatScream
4
Das _ideines Dokuments aus einer $groupPhase kann null sein.
Wdberkeley
1
Was wird das Ergebnis davon sein? Wenn ich laufe, bekomme ich alle Dokumente, die ich brauche, ich möchte nur die doppelten IDs / Namen.
Kannan T
24

Sie können das finden listvon duplicateNamen unter Verwendung der folgenden aggregatePipeline:

  • GroupAlle Datensätze haben ähnliche name.
  • Matchdiejenigen groupsmit Aufzeichnungen größer als 1.
  • Dann groupnochmal zu projectallen doppelten Namen als array.

Der Code:

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" ] }
BatScream
quelle
10

Die Antwort, die anhic gegeben hat, kann sehr ineffizient sein, wenn Sie über eine große Datenbank verfügen und der Attributname nur in einigen Dokumenten vorhanden ist.

Um die Effizienz zu verbessern, können Sie der Aggregation eine $ -Match hinzufügen.

db.collection.aggregate(
    {"$match": {"name" :{ "$ne" : null } } }, 
    {"$group" : {"_id": "$name", "count": { "$sum": 1 } } },
    {"$match": {"count" : {"$gt": 1} } }, 
    {"$project": {"name" : "$_id", "_id" : 0} }
)
Juanín
quelle
3
db.getCollection('orders').aggregate([  
    {$group: { 
            _id: {name: "$name"},
            uniqueIds: {$addToSet: "$_id"},
            count: {$sum: 1}
        } 
    },
    {$match: { 
        count: {"$gt": 1}
        }
    }
])

Erste Gruppe Fragen Sie die Gruppe nach den Feldern ab.

Dann überprüfen wir die eindeutige ID und zählen sie. Wenn die Anzahl größer als 1 ist, ist das Feld in der gesamten Sammlung doppelt vorhanden, sodass das Ding von $ match query behandelt werden soll.

Aman Shrivastava
quelle
1
Ich habe es nicht geschafft, dass dies auch für mich funktioniert. Down Voting!
Mathieu G
Dieser Beitrag ist alt, kann aber jemandem helfen. check this out Ich werde in meinem Lokal nachsehen, ob es funktioniert. Sogar ich bin auf einen Blog gestoßen. Guck dir das mal bitte an. compose.com/articles/finding-duplicate-documents-in-mongodb
Aman shrivastava
Ich konnte es zum Laufen bringen - bearbeitet, um auf die bestätigte Arbeitsversion zu aktualisieren.
AL Strine