se você estiver preparado para simplesmente descartar todas as outras duplicatas, basicamente você deseja
.aggregate()
para coletar os documentos com o mesmo RegisterNumber
valor e remova todos os outros documentos que não sejam a primeira correspondência. O MongoDB 3.0.x não possui alguns dos auxiliares modernos, mas o básico que
.aggregate()
retorna um cursor para grandes conjuntos de resultados do processo e a presença de "bulk operations"
para desempenho de gravação ainda existe:var bulk = db.collection.initializeOrderedBulkOp();
var count = 0;
db.collection.aggregate([
// Group on unique value storing _id values to array and count
{ "$group": {
"_id": "$RegisterNumber",
"ids": { "$push": "$_id" },
"count": { "$sum": 1 }
}},
// Only return things that matched more than once. i.e a duplicate
{ "$match": { "count": { "$gt": 1 } } }
]).forEach(function(doc) {
var keep = doc.ids.shift(); // takes the first _id from the array
bulk.find({ "_id": { "$in": doc.ids }}).remove(); // remove all remaining _id matches
count++;
if ( count % 500 == 0 ) { // only actually write per 500 operations
bulk.execute();
bulk = db.collection.initializeOrderedBulkOp(); // re-init after execute
}
});
// Clear any queued operations
if ( count % 500 != 0 )
bulk.execute();
Em versões mais modernas ( 3.2 e superiores ) é preferível usar
bulkWrite()
em vez de. Observe que isso é uma coisa de 'biblioteca de cliente', pois os mesmos métodos "em massa" mostrados acima são realmente chamados "sob o capô":var ops = [];
db.collection.aggregate([
{ "$group": {
"_id": "$RegisterNumber",
"ids": { "$push": "$id" },
"count": { "$sum": 1 }
}},
{ "$match": { "count": { "$gt": 1 } } }
]).forEach( doc => {
var keep = doc.ids.shift();
ops = [
...ops,
{
"deleteMany": { "filter": { "_id": { "$in": doc.ids } } }
}
];
if (ops.length >= 500) {
db.collection.bulkWrite(ops);
ops = [];
}
});
if (ops.length > 0)
db.collection.bulkWrite(ops);
Então
$group
reúne tudo através do $RegisterNumber
value e coleta o documento correspondente _id
valores para uma matriz. Você mantém a contagem de quantas vezes isso acontece usando $sum
. Em seguida, filtre quaisquer documentos que tenham apenas uma contagem de
1
uma vez que esses claramente não são duplicados. Passando para o loop você remove a primeira ocorrência de
_id
na lista coletada para a chave com .shift()
, deixando apenas outras "duplicatas" na matriz. Eles são passados para a operação "remove" com
$in
como uma "lista" de documentos para combinar e remover. O processo geralmente é o mesmo se você precisar de algo mais complexo, como mesclar detalhes de outros documentos duplicados, só que você pode precisar de mais cuidado ao fazer algo como converter o caso da "chave única" e, portanto, remover as duplicatas primeiro antes de escrever as alterações no documento a ser modificado.
De qualquer forma, a agregação destacará os documentos que realmente são "duplicados". A lógica de processamento restante é baseada no que você realmente deseja fazer com essas informações depois de identificá-las.