Se não for possível usar um campo exclusivo como chave de fragmento ou se for necessário impor a exclusividade em vários campos, crie outra coleção para atuar como uma coleção proxy.
Sobre esta tarefa
Um cluster fragmentado impõe uma restrição exclusiva entre shards somente quando o índice único está na chave de shard ou inclui a chave de shard como um prefixo. Uma coleção de proxy contorna essa restrição: a coleção de proxy contém uma referência ao documento original e a chave exclusiva, e seu aplicação grava primeiro na coleção de proxy.
Ao usar uma proxy collection, considere o seguinte:
Seu aplicação deve detectar erros ao inserir documentos na coleção de proxy. Escreva para ambas as coleções em uma transação para que as coleções não possam dividir se qualquer uma das inserções falhar.
Se a coleção de proxy exigir fragmentação, você deverá fragmentar o único campo no qual deseja impor a exclusividade.
Cada campo exige sua própria coleção de proxy. Para impor exclusividade em mais de um campo usando coleção de proxy fragmentadas, você deve ter uma coleção de proxy para cada campo. Se você criar vários índices únicos em uma única coleção de proxy, não poderá fragmentar a coleção de proxy.
Essa abordagem requer gerar o valor
_idem seu aplicação em vez de permitir que o MongoDB o crie automaticamente na inserção do documento , para que ambos os documentos compartilhem o mesmo_id.
Para obter o conjunto completo de restrições que se aplicam a índices exclusivos em coleções fragmentadas, consulte Manter exclusividade em clusters fragmentados.
Antes de começar
Identifique o campo que exige uma restrição exclusiva, mas não pode fazer parte da chave de fragmento.
Confirme que nenhum documento existente viola a restrição de exclusividade do campo.
Conecte o
mongosha uma instância domongos.
Passos
Considere uma collection records que armazena informações de usuário. O campo email não é a chave de fragmento, mas precisa ser único. A coleção proxy contém os seguintes campos:
{ "_id" : ObjectId("..."), "email" : "<string>"}Escreva para ambas as coleções em uma transação.
Insira um documento contendo o campo de destino e um ID exclusivo gerado na coleção proxy e, em seguida, insira o documento completo na coleção records. Execute ambas as inserções em uma transação para que o MongoDB aplique ambas as gravações ou nenhuma:
// 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();Se o valor email já existir na coleção proxy, o índice único rejeitará a inserção e a transação será cancelada, então nenhum documento será adicionado a records.