php mongodb mongodb-query aggregation-framework

php - Documentos duplicados de MongoDB incluso después de agregar una clave única



mongodb-query aggregation-framework (2)

Creé una colección y agregué una clave única como esta

db.user_services.createIndex({"uid":1 , "sid": 1},{unique:true,dropDups: true})

La colección se parece a esto "user_services"

{ "_id" : ObjectId("55068b35f791c7f81000002d"), "uid" : 15, "sid" : 1, "rate" : 5 }, { "_id" : ObjectId("55068b35f791c7f81000002f"), "uid" : 15, "sid" : 1, "rate" : 4 }

Problema:

Estoy usando el controlador php para insertar documentos con el mismo uid y sid y se está insertando.

Lo que quiero

  1. En Mongo Shell: agregue una clave única en uid y sid sin documentos duplicados con el mismo uid y sid.
  2. En el lado de PHP: tener algo como mysql "insertar (valor) en la clave duplicada tasa de actualización = tasa + 1" Es decir, cada vez que intento insertar un documento, debería insertarse si no fuera así, debería actualizar el campo de velocidad del documento

Siento que la respuesta más popular actual es un poco demasiado local y detallada para una operación MongoDB tan elemental: eliminar duplicados de mongo con una tecla.

Eliminar duplicados con una clave para mongo> 3.0 es simple. Simplemente ejecute esta consulta, reemplazando yourDuplicateKey y suponiendo que _id es su clave principal (asegúrese de mongodump por si acaso):

db.yourCollection.aggregate([ { "$group": { "_id": { "yourDuplicateKey": "$yourDuplicateKey" }, "dups": { "$push": "$_id" }, "count": { "$sum": 1 } }}, { "$match": { "count": { "$gt": 1 } }} ]).forEach(function(doc) { doc.dups.shift(); db.yourCollection.remove({ "_id": {"$in": doc.dups }}); });


Felicidades, parece que has encontrado un error. Esto solo ocurre con MongoDB 3.0.0 en mis pruebas, o al menos no está presente en MongoDB 2.6.6. Error ahora registrado en SERVER-17599

NOTA : en realidad no es un "problema" pero se confirmó "por diseño" Descartó la opción para la versión 3.0.0. Sin embargo, todavía aparece en la documentation .

El problema es que no se está creando el índice y los errores cuando intenta crear esto en una colección con duplicados existentes en los campos de "clave compuesta". En lo anterior, la creación del índice debería producir esto en el shell:

{ "createdCollectionAutomatically" : false, "numIndexesBefore" : 1, "errmsg" : "exception: E11000 duplicate key error dup key: { : 15.0, : 1.0 }", "code" : 11000, "ok" : 0 }

Cuando no haya duplicados presentes, puede crear el índice como lo está intentando actualmente y se creará.

Para evitar esto, primero elimine los duplicados con un procedimiento como este:

db.events.aggregate([ { "$group": { "_id": { "uid": "$uid", "sid": "$sid" }, "dups": { "$push": "$_id" }, "count": { "$sum": 1 } }}, { "$match": { "count": { "$gt": 1 } }} ]).forEach(function(doc) { doc.dups.shift(); db.events.remove({ "_id": {"$in": doc.dups }}); }); db.events.createIndex({"uid":1 , "sid": 1},{unique:true})

Luego, no se insertarán más inserciones que contengan datos duplicados y se registrará el error apropiado.

La nota final aquí es que "dropDups" es / no era una solución muy elegante para eliminar datos duplicados. Realmente quieres algo con más control como se demostró anteriormente.

Para la segunda parte, en lugar de usar .insert() use el método .update() . Tiene una opción "upsert"

$collection->update( array( "uid" => 1, "sid" => 1 ), array( ''$set'' => $someData ), array( ''upsert'' => true ) );

Por lo tanto, los documentos "encontrados" se "modifican" y los documentos no encontrados se "insertan". También vea $setOnInsert para una forma de crear solo ciertos datos cuando el documento se inserta realmente y no cuando se modifica.

Para su intento específico, la sintaxis correcta de .update() son tres argumentos. "consulta", "actualización" y "opciones":

$collection->update( array( "uid" => 1, "sid" => 1 ), array( ''$set'' => array( "field" => "this" ), ''$inc'' => array( "counter" => 1 ), ''$setOnInsert'' => array( "newField" => "another" ) ), array( "upsert" => true ) );

Ninguna de las operaciones de actualización tiene permitido "acceder a la misma ruta" que la utilizada en otra operación de actualización en esa sección del documento "actualizar".