Si no puede utilizar un campo único como clave de fragmentación, o si necesita garantizar la unicidad en varios campos, cree otra colección que actúe como colección proxy.
Acerca de esta tarea
Un clúster fragmentado impone una restricción de unicidad entre fragmentos solo cuando el índice único se encuentra en la clave del fragmento o incluye la clave del fragmento como prefijo. Una colección proxy sortea esta restricción: la colección proxy contiene tanto una referencia al documento original como la clave única, y la aplicación escribe primero en la colección proxy.
Cuando utilice una colección proxy, tenga en cuenta lo siguiente:
Tu aplicación debe detectar errores al insertar documentos en la colección proxy. Escribe en ambas colecciones dentro de una misma transacción para evitar que se produzcan errores de inserción si alguna falla.
Si la colección proxy requiere particionado, se debe particionar en el único campo en el que se desea aplicar la unicidad.
Cada campo requiere su propia colección proxy. Para garantizar la unicidad en más de un campo mediante colecciones proxy fragmentadas, debe tener una colección proxy para cada campo. Si crea varios índices únicos en una sola colección proxy, no podrá fragmentarla.
Este enfoque requiere generar el valor
_iden su aplicación en lugar de dejar que MongoDB lo cree automáticamente al insertar el documento, de modo que ambos documentos compartan el mismo_id.
Para consultar el conjunto completo de restricciones que se aplican a los índices únicos en colecciones fragmentadas, consulte la sección "Mantener la unicidad en clústeres fragmentados".
Antes de comenzar
Identifique el campo que requiere una restricción única pero que no puede formar parte de la clave de fragmentación.
Confirme que ningún documento existente infringe la restricción de unicidad para el campo.
Conectar
mongosha una instancia demongos.
Pasos
Consideremos una colección records que almacena información de usuario. El campo email no es la clave de fragmentación, pero debe ser único. La colección proxy contiene los siguientes campos:
{ "_id" : ObjectId("..."), "email" : "<string>"}Escribir en ambas colecciones en una misma transacción.
Inserta un documento que contenga el campo objetivo y un ID único generado en la colección proxy, luego inserta el documento completo en la colección records. Ejecuta ambas inserciones en una transacción para que MongoDB aplique ambas escrituras o ninguna:
// Start a sessionsession = db.getMongo().startSession( { readPreference: { mode: "primary" } } );proxy = session.getDatabase( db.getName() ).proxy;records = session.getDatabase( db.getName() ).records;
var primary_id = ObjectId();
// Start a transactionsession.startTransaction( { readConcern: { level: "local" }, writeConcern: { w: "majority" } } );
// Operations inside the transactiontry { proxy.insertOne( { "_id" : primary_id, "email" : "example@example.net" } );
records.insertOne( { "_id" : primary_id, "email" : "example@example.net", // additional information... } );} catch (error) { // A duplicate email value fails the proxy insert and // cancels the transaction session.abortTransaction(); throw error;}// Commit the transaction using write concern set at transaction startsession.commitTransaction();session.endSession();Si el valor email ya existe en la colección proxy, el índice único rechaza la inserción y la transacción se aborta, por lo que no se agrega ningún documento a records.