Nuestro equipo de redactores ha estado mucho tiempo buscando para darle resolución a tus interrogantes, te ofrecemos la resolución por eso deseamos resultarte de mucha apoyo.
Solución:
La respuesta aceptada es terriblemente lenta en colecciones grandes y no devuelve el _id
s de los registros duplicados.
La agregación es mucho más rápida y puede devolver el _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
]);
En la primera etapa de la canalización de agregación, el operador $group agrega documentos por el name
campo y tiendas en uniqueIds
cada _id
valor de los registros agrupados. El operador $sum suma los valores de los campos que se le pasan, en este caso la constante 1
– contando así el número de registros agrupados en el count
campo.
En la segunda etapa de la canalización, usamos $match para filtrar documentos con un count
de al menos 2, es decir, duplicados.
Luego, ordenamos primero los duplicados más frecuentes y limitamos los resultados a los 10 principales.
Esta consulta generará hasta $limit
registros con nombres duplicados, junto con sus _id
s. Por ejemplo:
"_id" :
"name" : "Toothpick"
,
"uniqueIds" : [
"xzuzJd2qatfJCSvkN",
"9bpewBsKbrGBQexv4",
"fi3Gscg9M64BQdArv",
],
"count" : 3
,
"_id" :
"name" : "Broom"
,
"uniqueIds" : [
"3vwny3YEj2qBsmmhA",
"gJeWGcuX6Wk69oFYD"
],
"count" : 2
Nota: esta solución es la más fácil de entender, pero no la mejor.
Puedes usar mapReduce
para saber cuántas veces un documento contiene un determinado campo:
var map = function()
if(this.name)
emit(this.name, 1);
var reduce = function(key, values)
return Array.sum(values);
var res = db.collection.mapReduce(map, reduce, out: inline : 1);
db[res.result].find(value: $gt: 1).sort(value: -1);
Para obtener una solución genérica de Mongo, consulte la receta del libro de cocina de MongoDB para encontrar duplicados usando group
. Tenga en cuenta que la agregación es más rápida y poderosa porque puede devolver el _id
s de los registros duplicados.
Para pymongo, la respuesta aceptada (usando mapReduce) no es tan eficiente. En su lugar, podemos usar el método de grupo:
$connection = 'mongodb://localhost:27017';
$con = new Mongo($connection); // mongo db connection
$db = $con->test; // database
$collection = $db->prb; // table
$keys = array("name" => 1); Select name field, group by it
// set intial values
$initial = array("count" => 0);
// JavaScript function to perform
$reduce = "function (obj, prev) prev.count++; ";
$g = $collection->group($keys, $initial, $reduce);
echo "";
print_r($g);
La salida será esta:
Array
(
[retval] => Array
(
[0] => Array
(
[name] =>
[count] => 1
)
[1] => Array
(
[name] => MongoDB
[count] => 2
)
)
[count] => 3
[keys] => 2
[ok] => 1
)
La consulta SQL equivalente sería: SELECT name, COUNT(name) FROM prb GROUP BY name
. Tenga en cuenta que todavía tenemos que filtrar los elementos con un recuento de 0 de la array. Nuevamente, consulte la receta del libro de cocina de MongoDB para encontrar duplicados usando group
para la solución canónica usando group
.