Encontre registros duplicados no MongoDB


116

Como eu encontraria campos duplicados em uma coleção mongo.

Gostaria de verificar se algum dos campos "nome" está duplicado.

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

Muito Obrigado!


5
O sinalizador duplicado para esta pergunta não é merecido. Esta questão pergunta como encontrar registros duplicados, não como evitá-los.
Harry King de

Respostas:


210

Use a agregação namee obtenha namecom count > 1:

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

Para classificar os resultados do máximo para o mínimo duplicado:

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

Para usar com outro nome de coluna diferente de "nome", altere " $ name " para " $ column_name "


1
"$match": {"_id" :{ "$ne" : null } - é desnecessário aqui, pois a segunda parte da instrução seria suficiente para filtrar o resultado. Portanto, apenas verificar o grupo que count > 1está tendo servirá.
BatScream

5
Tks @BatScream. {"$ ne": null} está lá apenas no caso de 'nome' ser nulo ou não existir. A agregação também contará como nula.
anhlc

1
Bem-vinda. Mas então por que verificar o _idcampo. É sempre garantido que não será nulo após a groupoperação.
BatScream

4
O _idde um documento de um $groupestágio pode ser nulo.
wdberkeley

1
Qual será o resultado disso? Se eu executar, recebo todos os documentos, o que eu preciso é querer apenas os IDs / nomes duplicados.
Kannan T

24

Você pode encontrar o listde duplicatenomes usando o seguinte aggregatepipeline:

  • Grouptodos os registros tendo similar name.
  • Matchaqueles groupscom registros maiores que 1.
  • Em seguida, groupnovamente para projecttodos os nomes duplicados como um array.

O código:

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

A resposta que anhic deu pode ser muito ineficiente se você tiver um grande banco de dados e o nome do atributo estiver presente apenas em alguns dos documentos.

Para melhorar a eficiência, você pode adicionar um $ match à agregação.

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}
        }
    }
])

Primeiro Grupo Consulte o grupo de acordo com os campos.

Em seguida, verificamos o Id único e o contamos. Se a contagem for maior que 1, o campo será duplicado em toda a coleção de forma que essa coisa seja tratada pela consulta $ match.


1
não foi capaz de fazer este funcionar para mim também. Votando!
Mathieu G

Esta postagem é antiga, mas pode ajudar alguém. verifique isso vou verificar no meu local está funcionando. Até eu encontrei um blog sobre isso. Por favor, dê uma olhada. compose.com/articles/finding-duplicate-documents-in-mongodb
Aman shrivastava

Consegui fazê-lo funcionar - editado para atualizar para a versão de trabalho confirmada.
AL Strine
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.