私が本質的にあなたの要点を理解するなら、あなたは基本的にしたいです
- 参照配列から不要なアイテムをプルします
- メイン参照フィールドの値を、変更された配列の最初の要素に設定します
そして、ドキュメントをネットワーク上で移動することなく、すべてを1回の更新で実行できます。
しかし、これは悲しいことにできません。これに関する主な問題は、更新されるドキュメント内の別のフィールドの値を参照する方法がないことです。それでも、反復せずにこれを行うには、変更されたにアクセスする必要もあります。 新しい最初の要素を取得するための配列。
おそらく1つのアプローチは、目的を達成するためにスキーマを再考することです。ここでの私のオプションは、参照ドキュメントを少し拡張し、メイン参照フィールドの必要性を排除します。
削除された参照がメイン参照である場合は、新しいメイン参照を配列の最初の要素に設定するだけでよいということを前提としています。そのことを念頭に置いて、次の構造を検討してください。
refs: [ { oid: "object1" }, { oid: "object2" }, { oid: "object5", main: true } ]
これらをoid
のドキュメントに変更する ObjectIdに設定されるプロパティは、デフォルトであるものを指定する追加のプロパティをドキュメントに持つオプションを提供します。これは簡単に照会でき、どのIDが主な参照であるかを判別できます。
ここで、oidフィールドの「object5」に一致するドキュメントが配列からプルされた場合にどうなるかについても検討します。
refs: [ { oid: "object1" }, { oid: "object2" } ]
したがって、main-reference
がどれであるかをクエリする場合 以前のロジックに従って、配列の最初のドキュメントを受け入れます。もちろん、アプリケーションの要件に応じて、別のmain-reference
を設定する場合 ドキュメントを変更するだけです
refs: [ { oid: "object1" }, { oid: "object2", main: true } ]
そして今、ロジックは、trueが優先的に発生するので、メインプロパティを持つ配列要素を選択するために残っています。上記のように、そのプロパティがどの要素ドキュメントにも存在しない場合は、最初の要素にフォールバックします。
これらすべてが消化されると、シェルで行われるように、すべてのドキュメントのその配列からオブジェクトへのすべての参照をプルする操作が非常に簡単になります(基本的に同じ形式がどのドライバーにも適用されます):
db.books.update(
{ "refs.oid": "object5" },
{ $pull: { refs: {oid: "object5"} } }, false, true )
upsert
であるクエリおよび更新操作に対する2つの追加の引数 およびmulti
それぞれ。この場合、upsert
存在するドキュメントとmulti
のみを変更したいので、あまり意味がありません。 一致したものをすべて更新したいという意味です。デフォルトでは、最初のドキュメントのみが変更されます。
当然、私はすべての表記を短縮しましたが、もちろん、値はあなたの意図に従って実際のObjectIdにすることができます。 main-reference
の主な使用法を推測することも合理的であるように思われました ドキュメントを取得した後です。 main-reference
を返すクエリを定義する 概説された論理に従うことによって可能であるはずです、しかしそれが現状で私はここにたくさんタイプしました、そして夕食のために休憩する必要があります:)
これは、スキーマを再考して、達成したいことに対するネットワークの反復を回避するための価値のある事例を示していると思います。