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

kerangka kerja agregasi mongodb cocok dengan dokumen bersarang

Menanyakan struktur ini untuk hasil yang Anda inginkan tidak mungkin dilakukan tanpa mengetahui semua forms yang mungkin ada nama sebelumnya, dan menggunakannya dalam kueri. Bagaimanapun, itu akan sangat berantakan. Karena itu, baca terus selagi saya menjelaskan cara melakukannya.

Ada masalah dengan struktur dokumen ini yang akan mencegah Anda melakukan analisis kueri yang wajar. Seperti yang terjadi, Anda harus mengetahui semua kemungkinan bidang nama formulir untuk memfilter apa pun.

Struktur Anda saat ini memiliki formulir yang berisi sub-dokumen, di mana setiap kunci berisi sub-dokumen lain dengan satu properti, status . Ini sulit dilintasi karena forms Anda elemen memiliki struktur arbitrer untuk setiap dokumen yang Anda buat. Itu artinya pola untuk turun ke status informasi yang ingin Anda bandingkan perubahannya untuk setiap dokumen dalam koleksi Anda.

Inilah yang saya maksud dengan jalan. Untuk mendapatkan status di elemen apa pun, Anda harus melakukan hal berikut

Dengan elemen kedua berubah sepanjang waktu. Tidak ada tidak mungkin ke wildcard sesuatu seperti ini karena penamaannya dianggap eksplisit.

Ini mungkin dianggap sebagai cara mudah untuk menerapkan serialisasi data dari formulir Anda tapi saya melihat lebih fleksibel alternatif. Yang Anda butuhkan adalah struktur dokumen yang dapat Anda telusuri dalam pola standar. Ini selalu sesuatu yang layak dipertimbangkan dalam desain. Ambil yang berikut ini:

{
    "_id" : "Tvq444454j",
    "name": "Jim",
    "forms": [
        {
             "name": "Jorney",
             "status":"closed"          
        },
        {
            "name": "Women",
            "status":"void"            
        },
        {
            "name": "Child",
            "status":"closed"           
        },
        {
            "name": "Farm",
            "status":"closed"            
        }  
    ]
}

Jadi struktur dokumen diubah menjadi forms elemen Array, dan alih-alih menempatkan bidang status di bawah kunci yang menamai "bidang formulir", kami memiliki setiap anggota Array sebagai sub-dokumen yang berisi "bidang formulir" name dan status . Jadi pengenal dan statusnya masih dipasangkan bersama tetapi hanya direpresentasikan sebagai sub-dokumen sekarang. Ini yang paling penting mengubah jalur akses ke kunci ini, seperti sekarang untuk keduanya nama field dan statusnya bisa kita lakukan

Apa ini artinya Anda dapat melakukan kueri untuk menemukan nama semua bidang dalam form atau semua status bidang dalam form , atau bahkan semua dokumen dengan name tertentu bidang dan status tertentu . Itu banyak lebih baik daripada apa yang bisa dilakukan dengan struktur aslinya.

Sekarang dalam kasus khusus Anda, Anda ingin mendapatkan hanya dokumen di mana semua kolom tidak void . Sekarang tidak ada cara dalam satu kueri untuk melakukan ini karena tidak ada operator untuk membandingkan semua elemen dalam array dengan cara ini dan melihat apakah mereka sama. Namun ada dua pendekatan yang dapat Anda ambil:

Yang pertama dan mungkin tidak seefisien itu adalah menanyakan semua dokumen yang berisi elemen dalam forms yang memiliki status dari "batal". Dengan ID dokumen yang dihasilkan, Anda dapat mengeluarkan kueri lain yang mengembalikan dokumen yang tidak memiliki ID yang ditentukan.

db.forms.find({ "forms.status": "void" },{ _id: 1})

db.forms.find({ _id: $not: { $in: [<Object1>,<Object2>,<Object3>,... ] } })

Mengingat ukuran hasil, ini mungkin tidak mungkin dan umumnya bukan ide yang baik karena operator pengecualian $not pada dasarnya memaksa pemindaian penuh koleksi, sehingga Anda tidak dapat menggunakan indeks.

Pendekatan lain adalah dengan menggunakan pipa agregasi sebagai berikut:

db.forms.aggregate([
    { "$unwind": "$forms" },
    { "$group": { "_id": "$_id", "status": { "$addToSet": "$forms.status" }}},
    { "$unwind": "$status" },
    { "$sort": { "_id": 1, "status": -1 }},
    { "$group": { "_id": "$_id", "status": { "$first": "$status"}}},
    { "$match":{ "status": "closed" }}
])

Tentu saja itu hanya akan mengembalikan _id untuk dokumen yang cocok, tetapi Anda dapat mengeluarkan kueri dengan $in dan mengembalikan seluruh dokumen yang cocok. Ini lebih baik daripada operator pengecualian yang digunakan sebelumnya, dan sekarang kita dapat menggunakan indeks untuk menghindari pemindaian koleksi penuh.

Sebagai pendekatan terakhir dan untuk yang terbaik pertimbangan kinerja, Anda dapat mengubah dokumen lagi sehingga di tingkat atas Anda menyimpan "status" apakah bidang apa pun dalam formulir dalam "void" atau "closed". Jadi di tingkat atas nilainya akan ditutup hanya jika semua item "ditutup" dan "tidak berlaku" jika ada sesuatu yang batal, dan seterusnya.

Yang terakhir itu berarti perubahan terprogram lebih lanjut, dan semua perubahan pada forms item perlu memperbarui bidang ini juga untuk mempertahankan "status". Namun, ini adalah cara paling efisien untuk menemukan dokumen yang Anda butuhkan dan mungkin patut dipertimbangkan.

EDIT :

Selain mengubah dokumen menjadi status master, formulir kueri tercepat pada struktur yang direvisi sebenarnya adalah:

db.forms.find({ "forms": { "$not": { "$elemMatch": { "status": "void" } } } })



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Dapatkan _id dari dokumen yang dimasukkan di MongoDB?

  2. Menghapus subdokumen dari array di MongodDB

  3. Spring Data Mongo - Metode kueri dan bidang Berbeda

  4. cara memeriksa dari driver, apakah server mongoDB sedang berjalan

  5. MongoDB untuk penggunaan komersial