sql >> データベース >  >> NoSQL >> MongoDB

複数の基準でネストされた配列からオブジェクトを削除する

    $pullできます 「外部配列」から「最初の一致」を実行し、次の操作を行うだけで「すべての内部要素」を削除します。

    db.Events.updateMany(
      {
        "Distributions.DistributionData": {
          "$elemMatch": {
            "Key": null,
            "Value": null,
            "Children": null
          }
        }
      },
      {
        "$pull": {
          "Distributions.$.DistributionData": { 
            "Key": null,
            "Value": null,
            "Children": null
          }
        }
      }
    )
    

    "Distributions"にエントリが1つしかない場合は、これで問題ありません。 配列またはこれらのエントリの少なくとも1つだけに、条件に一致する子配列エントリがあります。これが、位置の$の方法です。 演算子は、MongoDBのすべてのバージョンで機能します。

    データの「外部」"Distributions"に「複数」の一致がある場合 配列の場合、MongoDB 3.6を使用している場合は、位置フィルター処理された$[<identifier>]を適用できます。 一致するすべてのエントリを変更する演算子:

    db.Events.updateMany(
      {
        "Distributions.DistributionData": {
          "$elemMatch": {
            "Key": null,
            "Value": null,
            "Children": null
          }
        }
      },
      {
        "$pull": {
          "Distributions.$[element].DistributionData": { 
            "Key": null,
            "Value": null,
            "Children": null
          }
        }
      },
      {
        "arrayFilters": [
          { "element.DistributionData": {
            "$elemMatch": {
              "Key": null,
              "Value": null,
              "Children": null
            }
          }}
        ]
      }
    )
    

    その場合、arrayFilters オプションは、「外部」配列のエントリを照合する条件を定義します。これにより、実際に照合されるすべてのものに適用できます。

    または実際に$pull以降 基本的にこれらの条件自体があります。代わりに、すべての$[]の位置を使用することもできます。 この場合の演算子:

    db.Event.updateMany(
      {
        "Distributions.DistributionData": {
          "$elemMatch": {
            "Key": null,
            "Value": null,
            "Children": null
          }
        }
      },
      {
        "$pull": {
          "Distributions.$[].DistributionData": { 
            "Key": null,
            "Value": null,
            "Children": null
          }
        }
      }
    )
    

    どちらの場合も、すべてのnullを含む内部アイテムを削除することにより、質問のドキュメントを変更します キー:

    {
            "_id" : UUID("cf397865-c000-4f51-8959-1aae84769706"),
            "CreationDateTime" : ISODate("2016-05-06T05:09:14.589Z"),
            "WKT" : "",
            "Distributions" : [
                    {
                            "_id" : UUID("bb95bedb-4baa-4ada-90b1-0d763e70ebfe"),
                            "DeliveryType" : 1,
                            "DistributionData" : [
                                    {
                                            "Key" : "Topic",
                                            "Value" : "Topics",
                                            "Children" : null
                                    },
                                    {
                                            "Key" : "Message",
                                            "Value" : "test",
                                            "Children" : null
                                    }
                            ],
                            "Schedules" : [
                                    ISODate("2016-05-06T05:09:56.988Z")
                            ]
                    }
            ]
    }
    

    「クエリ」条件はすべて$elemMatchを使用します ドキュメント選択用。これは実際には位置$に必要です 「最初の一致」に使用される「位置インデックス」を取得するための演算子。これは実際には、位置フィルタリングされた$[<identifier>]の「要件」ではありません。 または位置的なすべての$[] 演算子、それはまだ有用なので、$pullのいずれかのその後の更新条件と一致しない更新用のドキュメントを考慮することさえありません またはarrayFilters オプション。

    $pullについて それ自体、ここでの条件は実際には「各」配列要素に適用されるため、$elemMatchは必要ありません。 すでに「要素」レベルを見ているので、その操作で。

    3番目の例は、位置がすべて$[]であることを示しています。 演算子はこれらの$pullを使用するだけです 各「内部」配列要素を考慮した条件であり、すべての「外部」配列要素にのみ適用されます。したがって、位置フィルタリングされた$[<identifier>]の実際のポイント 式は、実際に「内部」条件に一致する「外部」配列要素を「のみ」処理することです。したがって、$elemMatchを使用する理由 各「内部」配列要素を一致させるための考慮事項。

    少なくとも実際にMongoDB3.6を使用していない場合は、最初のフォームを使用しており、更新によって条件に一致する要素が残っていないことを示す変更されたドキュメントが最終的に返されないまで、これを繰り返す可能性があります。

    mongodbで複数の配列要素を更新する方法のアプローチとして、「代替案」に関するより詳細な記述がありますが、データが最初のケースに適合するか、実際にMongoDB 3.6が利用可能である限り、これは正しいですここにアプローチします。

    MongoDB3.6の新しい構文の完全な効果を確認したい場合。これは、ここで更新ステートメントを検証するために使用した質問のドキュメントへの変更です:

    {
        "_id" : UUID("cf397865-c000-4f51-8959-1aae84769706"),
        "CreationDateTime" : ISODate("2016-05-06T05:09:14.589Z"),
        "WKT" : "",
        "Distributions" : [
                {
                        "_id" : UUID("bb95bedb-4baa-4ada-90b1-0d763e70ebfe"),
                        "DeliveryType" : 1,
                        "DistributionData" : [
                                {
                                        "Key" : "Topic",
                                        "Value" : "Topics",
                                        "Children" : null
                                },
                                {
                                        "Key" : null,
                                        "Value" : null,
                                        "Children" : null
                                },
                                {
                                        "Key" : "Message",
                                        "Value" : "test",
                                        "Children" : null
                                },
                                {
                                        "Key" : null,
                                        "Value" : null,
                                        "Children" : null
                                }
                        ],
                        "Schedules" : [
                                ISODate("2016-05-06T05:09:56.988Z")
                        ]
                },
                {
                        "_id" : UUID("bb95bedb-4baa-4ada-90b1-0d763e70ebfe"),
                        "DeliveryType" : 1,
                        "DistributionData" : [
                                {
                                        "Key" : "Topic",
                                        "Value" : "Topics",
                                        "Children" : null
                                },
                                {
                                        "Key" : null,
                                        "Value" : null,
                                        "Children" : null
                                },
                                {
                                        "Key" : "Message",
                                        "Value" : "test",
                                        "Children" : null
                                },
                                {
                                        "Key" : null,
                                        "Value" : null,
                                        "Children" : null
                                }
                        ],
                        "Schedules" : [
                                ISODate("2016-05-06T05:09:56.988Z")
                        ]
                }
        ]
    }
    

    これは基本的に「outer」と「inner」の両方のエントリを複製して、ステートメントがすべてのnullを削除する方法を示しています。 値。

    arrayFilters .update()の「options」引数で指定されます メソッドと同様に、構文は通常、すべての最新リリースのドライバーバージョン、およびMongoDB3.6のリリース以前のバージョンと互換性があります。

    ただし、これはmongoには当てはまりません。 シェル、メソッドがそこで実装される方法(「下位互換性のために皮肉なことに」)arrayFilters 引数は、以前のMongoDBサーバーバージョンおよび「レガシー」.update()との「下位互換性」を提供するためにオプションを解析する内部メソッドによって認識および削除されません。 API呼び出しの構文。

    したがって、mongoでコマンドを使用する場合 シェルまたはその他の「シェルベース」の製品(特にRobo 3T)には、3.6以降の開発ブランチまたは製品リリースの最新バージョンが必要です。

    特にここでのRobo3Tは、MongoDB3.4シェルに基づいていることに変わりはありません。そのため、対応するMongoDB 3.6インスタンスに接続する場合でも、これらのオプションはこのプログラムからサーバーに渡されません。同じ制限がない他の製品もありますが、シェルとサポートされている製品のみを使用することをお勧めします。




    1. gradleはローカル作品を構築します。 Dockerコンテナーでは、そうではありません。なぜ?

    2. MongoDBのクエリ結果のフィールドの名前を変更します

    3. MongoError:最初の接続でサーバーに接続できませんでした

    4. 接続ごとに新しいRedisクライアントを作成する必要がありますか?