Przyjęta odpowiedź jest strasznie powolna w przypadku dużych kolekcji i nie zwraca _id
s zduplikowanych rekordów.
Agregacja jest znacznie szybsza i może zwrócić _id
s:
db.collection.aggregate([
{ $group: {
_id: { name: "$name" }, // replace `name` here twice
uniqueIds: { $addToSet: "$_id" },
count: { $sum: 1 }
} },
{ $match: {
count: { $gte: 2 }
} },
{ $sort : { count : -1} },
{ $limit : 10 }
]);
W pierwszym etapie potoku agregacji $groupoperator agreguje dokumenty według name
pole i przechowuje w uniqueIds
każdy _id
wartość zgrupowanych rekordów.Operator $sum dodaje wartości przekazanych mu pól, w tym przypadku stałą 1
- w ten sposób zliczając liczbę zgrupowanych rekordów do count
pole.
W drugim etapie potoku używamy $matchto filtrować dokumenty z count
co najmniej 2, czyli duplikaty.
Następnie najpierw sortujemy najczęstsze duplikaty i ograniczamy wyniki do pierwszej dziesiątki
To zapytanie wygeneruje do $limit
rekordy o zduplikowanych nazwach, wraz z ich _id
s. Na przykład:
{
"_id" : {
"name" : "Toothpick"
},
"uniqueIds" : [
"xzuzJd2qatfJCSvkN",
"9bpewBsKbrGBQexv4",
"fi3Gscg9M64BQdArv",
],
"count" : 3
},
{
"_id" : {
"name" : "Broom"
},
"uniqueIds" : [
"3vwny3YEj2qBsmmhA",
"gJeWGcuX6Wk69oFYD"
],
"count" : 2
}