一意のフィールドをシャードキーとして 使用できない 場合や、複数のフィールドに一意性を適用する必要がある場合は、 プロキシコレクションとして機能する別のコレクションを作成します。
このタスクについて
シャーディングされたクラスターは、ユニークインデックスがシャードキーにある、またはプレフィックスとしてシャードキーが含まれている場合にのみ、シャード全体に一意の制約を強制します。プロキシコレクションはその制約を回避します。プロキシコレクションには元のドキュメントへの参照と一意のキーの両方が含まれており、アプリケーションは最初にプロキシコレクションに書込みます。
プロキシコレクションを使用する場合は、次の点を考慮してください。
プロキシ コレクションでシャーディングが必要な場合は、一意性を強制したい単一フィールドでシャードする必要があります。
各フィールドには独自の プロキシコレクションが必要です。シャーディングされたプロキシ コレクションを使用して複数のフィールドに一意性を強制するには、フィールドごとに 1 つのプロキシコレクションが必要です。 1 つの プロキシコレクションに複数の一意なインデックスを作成した場合、 プロキシコレクションをシャードすることは できません 。
このアプローチでは、ドキュメントの挿入時にMongoDB が自動的にそれを作成するのではなく、アプリケーション内で
_id値を生成する必要があり、両方のドキュメントが同じ_idを共有する必要があります。
シャーディングされたコレクションの一意のインデックスに適用される制約の完全なセットについては、「 シャーディングされたクラスターで一意性を維持する 」を参照してください。
始める前に
一意の制約 を必要とするが、シャードキーの一部にすることはできないフィールドを識別します。
既存のドキュメントがフィールドの一意の制約に違反していないことを確認します。
手順
ユーザー情報を保存するコレクションrecords について考えてみましょう。フィールドemail はシャードキーではありませんが、一意である必要があります。 proxyコレクションには次のフィールドが含まれています。
{ "_id" : ObjectId("..."), "email" : "<string>"}トランザクション内の両方のコレクションに書込みます。
ターゲットフィールドと生成された一意のIDを含むドキュメントをproxyコレクションに挿入し、完全なドキュメントをrecordsコレクションに挿入します。トランザクション内で両方の挿入を実行し、 MongoDB が両方の書込みを適用するか、またはその両方を適用しないようにします。
// 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();email 値がすでに proxyコレクションに存在する場合、ユニークインデックスは挿入を拒否し、トランザクションは中止されるため、records にドキュメントは追加されません。