MongoDB
 sql >> Teknologi Basis Data >  >> NoSQL >> MongoDB

Hapus Objek dari Array Bersarang dengan Beberapa Kriteria

Anda dapat $pull "kecocokan pertama" dari "array luar" dengan menghapus "semua elemen dalam" hanya dengan melakukan:

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

Tidak apa-apa jika Anda hanya memiliki satu entri di "Distributions" array atau setidaknya hanya satu dari entri tersebut yang memiliki entri larik anak yang akan cocok dengan kondisinya. Ini adalah bagaimana posisi $ operator bekerja dengan semua versi MongoDB.

Jika data memiliki "beberapa" kecocokan di "Distributions" "luar" array maka jika Anda memiliki MongoDB 3.6, Anda dapat menerapkan $[<identifier>] yang difilter posisi operator untuk mengubah semua entri yang cocok:

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
        }
      }}
    ]
  }
)

Dalam hal ini arrayFilters option mendefinisikan kondisi di mana kita mencocokkan entri dalam larik "luar" sehingga ini sebenarnya dapat diterapkan ke semua yang cocok.

Atau memang sejak $pull dasarnya memiliki kondisi itu sendiri, maka Anda dapat secara bergantian menggunakan posisi semua $[] operator dalam hal ini:

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

Kedua kasus mengubah dokumen dalam pertanyaan dengan menghapus item dalam dengan semua null kunci:

{
        "_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")
                        ]
                }
        ]
}

Kondisi "query" semuanya menggunakan $elemMatch untuk pemilihan dokumen. Ini sebenarnya diperlukan untuk posisi $ operator untuk mendapatkan "indeks posisi" yang digunakan untuk "pertandingan pertama". Meskipun ini sebenarnya bukan "persyaratan" untuk $[<identifier>] yang difilter posisi atau posisi semua $[] operator, ini masih berguna sehingga Anda bahkan tidak mempertimbangkan dokumen untuk pembaruan yang tidak akan cocok dengan kondisi pembaruan selanjutnya baik dari $pull atau arrayFilters pilihan.

Adapun $pull sendiri, kondisi di sini sebenarnya berlaku untuk elemen larik "setiap", jadi tidak perlu $elemMatch dalam operasi itu karena kita sudah melihat level "elemen".

Contoh ketiga menunjukkan bahwa posisi semua $[] operator cukup menggunakan $pull kondisi dengan mempertimbangkan setiap elemen larik "dalam" dan hanya akan berlaku untuk SEMUA elemen larik "luar". Jadi titik sebenarnya dari $[<identifier>] . yang difilter posisi ekspresi adalah untuk "hanya" memproses elemen larik "luar" yang benar-benar cocok dengan kondisi "dalam". Oleh karena itu mengapa kami menggunakan $elemMatch dalam pertimbangan untuk mencocokkan setiap elemen larik "dalam".

Jika Anda tidak benar-benar memiliki MongoDB 3.6 setidaknya maka Anda menggunakan formulir pertama dan kemungkinan akan mengulanginya sampai pembaruan akhirnya mengembalikan tidak ada lagi dokumen yang dimodifikasi yang menunjukkan bahwa tidak ada lagi elemen yang tersisa yang cocok dengan kondisi tersebut.

Ada tulisan yang jauh lebih rinci tentang "alternatif" sebagai pendekatan di Cara Memperbarui Beberapa Elemen Array di mongodb, tetapi selama data Anda sesuai dengan kasus awal atau Anda benar-benar memiliki MongoDB 3.6 tersedia, maka ini adalah yang benar mendekat ke sini.

Jika Anda ingin melihat efek penuh dari sintaks baru untuk MongoDB 3.6. ini adalah perubahan pada dokumen dalam pertanyaan yang saya gunakan untuk memverifikasi pernyataan pembaruan di sini:

{
    "_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")
                    ]
            }
    ]
}

Yang pada dasarnya menduplikasi beberapa entri baik "luar" dan "dalam" untuk menunjukkan bagaimana pernyataan menghapus semua null nilai.

CATATAN arrayFilters ditentukan dalam argumen "opsi" untuk .update() dan seperti metode, sintaks umumnya kompatibel dengan semua versi driver rilis terbaru dan bahkan sebelum rilis MongoDB 3.6.

Namun ini tidak berlaku untuk mongo shell, karena cara metode ini diterapkan di sana ( "ironisnya untuk kompatibilitas ke belakang" ) arrayFilters argumen tidak dikenali dan dihapus oleh metode internal yang mem-parsing opsi untuk memberikan "kompatibilitas mundur" dengan versi server MongoDB sebelumnya dan .update() "warisan" Sintaks panggilan API.

Jadi jika Anda ingin menggunakan perintah di mongo shell atau produk "berbasis shell" lainnya (terutama Robo 3T ) Anda memerlukan versi terbaru baik dari cabang pengembangan atau rilis produksi mulai 3.6 atau lebih tinggi.

Robo 3T terutama di sini masih terikat pada shell MongoDB 3.4. Jadi, bahkan saat menghubungkan ke instans MongoDB 3.6 yang mumpuni, opsi ini tidak akan diteruskan ke server dari program ini. Disarankan untuk tetap menggunakan shell dan produk yang didukung saja, meskipun ada beberapa penawaran lain yang tidak memiliki batasan yang sama.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Aplikasi gagal untuk memulai (port 8080) tidak tersedia

  2. Transaksi Mongo DB 4.0 Dengan Mongoose &NodeJs, Express

  3. MongoDB:Hanya mengambil dokumen yang dibuat dalam 24 jam terakhir?

  4. Berapa ukuran maksimal operasi batch MongoDB?

  5. Gambaran Umum Pengindeksan Basis Data untuk MongoDB