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

Jumlahkan array bersarang di node.js mongodb

Mari kita mulai dengan penafian dasar bahwa bagian utama dari jawaban masalah telah dijawab di sini di Temukan di MongoDB Array Bersarang Ganda . Dan "sebagai catatan" Ganda juga berlaku untuk Tiga kali atau Quadrupal atau APA SAJA tingkat bersarang karena pada dasarnya prinsip yang sama SELALU .

Poin utama lainnya dari jawaban apa pun adalah juga Jangan NEST Array , karena seperti yang dijelaskan dalam jawaban itu juga ( dan saya telah mengulangi banyak . ini kali ), apa pun alasan Anda "berpikir" yang Anda miliki untuk "bersarang" sebenarnya tidak memberikan keuntungan yang Anda rasa akan. Sebenarnya "bersarang" benar-benar hanya membuat hidup jauh lebih sulit.

Masalah Bersarang

Kesalahpahaman utama dari setiap terjemahan struktur data dari model "relasional" hampir selalu ditafsirkan sebagai "tambahkan tingkat array bersarang" untuk setiap model terkait. Apa yang Anda sajikan di sini tidak terkecuali untuk kesalahpahaman ini karena tampaknya sangat "dinormalisasi" sehingga setiap sub-array berisi item terkait dengan induknya.

MongoDB adalah database berbasis "dokumen", sehingga cukup memungkinkan Anda untuk melakukan ini atau bahkan konten struktur data apa pun yang pada dasarnya Anda inginkan. Namun, itu tidak berarti bahwa data dalam bentuk seperti itu mudah digunakan atau bahkan praktis untuk tujuan yang sebenarnya.

Mari kita isi skema dengan beberapa data aktual untuk ditunjukkan:

{
  "_id": 1,
  "first_level": [
    {
      "first_item": "A",
      "second_level": [
        {
          "second_item": "A",
          "third_level": [
            { 
              "third_item": "A",
              "forth_level": [
                { 
                  "price": 1,
                  "sales_date": new Date("2018-10-31"),
                  "quantity": 1
                },
                { 
                  "price": 1,
                  "sales_date": new Date("2018-11-01"),
                  "quantity": 1
                },
                { 
                  "price": 1,
                  "sales_date": new Date("2018-11-02"),
                  "quantity": 1
                },
              ]
            },
            { 
              "third_item": "B",
              "forth_level": [
                { 
                  "price": 1,
                  "sales_date": new Date("2018-10-31"),
                  "quantity": 1
                },
              ]
            }
          ]
        },
        {
          "second_item": "A",
          "third_level": [
            { 
              "third_item": "B",
              "forth_level": [
                { 
                  "price": 1,
                  "sales_date": new Date("2018-11-03"),
                  "quantity": 1
                },
              ]
            }
          ]
        }
      ]
    },
    {
      "first_item": "A",
      "second_level": [
        {
          "second_item": "B",
          "third_level": [
            { 
              "third_item": "A",
              "forth_level": [
                { 
                  "price": 1,
                  "sales_date": new Date("2018-11-03"),
                  "quantity": 1
                },
              ]
            }
          ]
        }
      ]
    }
  ]
},
{
  "_id": 2,
  "first_level": [
    {
      "first_item": "A",
      "second_level": [
        {
          "second_item": "A",
          "third_level": [
            { 
              "third_item": "A",
              "forth_level": [
                { 
                  "price": 2,
                  "sales_date": new Date("2018-11-03"),
                  "quantity": 1
                },
                { 
                  "price": 1,
                  "sales_date": new Date("2018-10-31"),
                  "quantity": 1
                },
                { 
                  "price": 1,
                  "sales_date": new Date("2018-11-03"),
                  "quantity": 1
                }
              ]
            }
          ]
        }
      ]
    }
  ]
},
{
  "_id": 3,
  "first_level": [
    {
      "first_item": "A",
      "second_level": [
        {
          "second_item": "B",
          "third_level": [
            { 
              "third_item": "A",
              "forth_level": [
                { 
                  "price": 1,
                  "sales_date": new Date("2018-11-03"),
                  "quantity": 1
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

Itu "sedikit" berbeda dari struktur dalam pertanyaan tetapi untuk tujuan demonstrasi memiliki hal-hal yang perlu kita lihat. Terutama ada array dalam dokumen yang memiliki item dengan sub-array, yang pada gilirannya memiliki item dalam sub-array dan seterusnya. "normalisasi" di sini tentu saja dengan pengidentifikasi pada setiap "level" sebagai "tipe item" atau apa pun yang sebenarnya Anda miliki.

Masalah intinya adalah Anda hanya ingin "sebagian" data dari dalam array bersarang ini, dan MongoDB benar-benar hanya ingin mengembalikan "dokumen", yang berarti Anda perlu melakukan beberapa manipulasi untuk mendapatkan "sub-" yang cocok. item".

Bahkan pada masalah "benar" memilih dokumen yang cocok dengan semua "sub-kriteria" ini memerlukan penggunaan $elemMatch untuk mendapatkan kombinasi kondisi yang benar pada setiap level elemen array. Anda tidak dapat langsung menggunakan "Notasi Titik" karena kebutuhan akan beberapa kondisi . Tanpa $elemMatch pernyataan Anda tidak mendapatkan "kombinasi" yang tepat dan hanya mendapatkan dokumen yang kondisinya benar pada apa saja elemen larik.

Adapun sebenarnya "memfilter isi array" maka itu sebenarnya bagian dari perbedaan tambahan:

db.collection.aggregate([
  { "$match": {
    "first_level": {
      "$elemMatch": {
        "first_item": "A",
        "second_level": {
          "$elemMatch": {
            "second_item": "A",
            "third_level": {
              "$elemMatch": {
                "third_item": "A",
                "forth_level": {
                  "$elemMatch": {
                    "sales_date": {
                      "$gte": new Date("2018-11-01"),
                      "$lt": new Date("2018-12-01")
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }},
  { "$addFields": {
    "first_level": {
      "$filter": {
        "input": {
          "$map": {
            "input": "$first_level",
            "in": {
              "first_item": "$$this.first_item",
              "second_level": {
                "$filter": {
                  "input": {
                    "$map": {
                      "input": "$$this.second_level",
                      "in": {
                        "second_item": "$$this.second_item",
                        "third_level": {
                          "$filter": {
                            "input": {
                              "$map": {
                                "input": "$$this.third_level",
                                 "in": {
                                   "third_item": "$$this.third_item",
                                   "forth_level": {
                                     "$filter": {
                                       "input": "$$this.forth_level",
                                       "cond": {
                                         "$and": [
                                           { "$gte": [ "$$this.sales_date", new Date("2018-11-01") ] },
                                           { "$lt": [ "$$this.sales_date", new Date("2018-12-01") ] }
                                         ]
                                       }
                                     }
                                   }
                                 } 
                              }
                            },
                            "cond": {
                              "$and": [
                                { "$eq": [ "$$this.third_item", "A" ] },
                                { "$gt": [ { "$size": "$$this.forth_level" }, 0 ] }
                              ]
                            }
                          }
                        }
                      }
                    }
                  },
                  "cond": {
                    "$and": [
                      { "$eq": [ "$$this.second_item", "A" ] },
                      { "$gt": [ { "$size": "$$this.third_level" }, 0 ] }
                    ]
                  }
                }
              }
            }
          }
        },
        "cond": {
          "$and": [
            { "$eq": [ "$$this.first_item", "A" ] },
            { "$gt": [ { "$size": "$$this.second_level" }, 0 ] }
          ]
        } 
      }
    }
  }},
  { "$unwind": "$first_level" },
  { "$unwind": "$first_level.second_level" },
  { "$unwind": "$first_level.second_level.third_level" },
  { "$unwind": "$first_level.second_level.third_level.forth_level" },
  { "$group": {
    "_id": {
      "date": "$first_level.second_level.third_level.forth_level.sales_date",
      "price": "$first_level.second_level.third_level.forth_level.price",
    },
    "quantity_sold": {
      "$avg": "$first_level.second_level.third_level.forth_level.quantity"
    } 
  }},
  { "$group": {
    "_id": "$_id.date",
    "prices": {
      "$push": {
        "price": "$_id.price",
        "quanity_sold": "$quantity_sold"
      }
    },
    "quanity_sold": { "$avg": "$quantity_sold" }
  }}
])

Ini paling tepat digambarkan sebagai "berantakan" dan "terlibat". Tidak hanya permintaan awal kami untuk pemilihan dokumen dengan $elemMatch lebih dari seteguk, tapi kemudian kami memiliki $filter dan $map pemrosesan untuk setiap level array. Seperti yang disebutkan sebelumnya, ini adalah polanya tidak peduli berapa banyak level sebenarnya.

Anda dapat secara bergantian melakukan $unwind dan $match kombinasi alih-alih memfilter array di tempat, tetapi ini menyebabkan overhead tambahan ke $unwind sebelum konten yang tidak diinginkan dihapus, jadi dalam rilis modern MongoDB, umumnya praktik yang lebih baik adalah $filter dari array terlebih dahulu.

Tempat akhir di sini adalah Anda ingin $group oleh elemen yang sebenarnya ada di dalam array, jadi Anda akhirnya perlu $unwind setiap level array sebelum ini.

"Pengelompokan" yang sebenarnya kemudian umumnya langsung menggunakan sales_date dan price properti untuk pertama akumulasi, lalu menambahkan tahap berikutnya ke $push price yang berbeda nilai rata-rata yang ingin Anda kumpulkan dalam setiap tanggal sebagai detik akumulasi.

CATATAN :Penanganan tanggal yang sebenarnya mungkin berbeda dalam penggunaan praktis tergantung pada perincian tempat Anda menyimpannya. Dalam contoh ini, semua tanggal sudah dibulatkan ke awal setiap "hari". Jika Anda benar-benar perlu mengumpulkan nilai "datetime" yang sebenarnya, maka Anda mungkin benar-benar menginginkan konstruksi seperti ini atau yang serupa:

{ "$group": {
  "_id": {
    "date": {
      "$dateFromParts": {
        "year": { "$year": "$first_level.second_level.third_level.forth_level.sales_date" },
        "month": { "$month": "$first_level.second_level.third_level.forth_level.sales_date" },
        "day": { "$dayOfMonth": "$first_level.second_level.third_level.forth_level.sales_date" }
      }
    }.
    "price": "$first_level.second_level.third_level.forth_level.price"
  }
  ...
}}

Menggunakan $dateFromParts dan operator agregasi tanggal lainnya untuk mengekstrak informasi "hari" dan menampilkan tanggal kembali dalam bentuk tersebut untuk akumulasi.

Mulai Denormalisasi

Apa yang harus jelas dari "kekacauan" di atas adalah bahwa bekerja dengan array bersarang tidak mudah. Struktur seperti itu umumnya bahkan tidak mungkin untuk memperbarui secara atom dalam rilis sebelum MongoDB 3.6, dan bahkan jika Anda bahkan tidak pernah memperbaruinya atau hidup dengan mengganti pada dasarnya seluruh array, mereka masih tidak mudah untuk ditanyakan. Inilah yang sedang ditampilkan kepada Anda.

Di mana Anda harus memiliki konten array dalam dokumen induk, biasanya disarankan untuk "meratakan" dan "denormalisasi" struktur seperti itu. Ini mungkin tampak bertentangan dengan pemikiran relasional, tetapi sebenarnya ini adalah cara terbaik untuk menangani data tersebut untuk alasan kinerja:

{
  "_id": 1,
  "data": [
    {
      "first_item": "A",
      "second_item": "A",
      "third_item": "A",
      "price": 1,
      "sales_date": new Date("2018-10-31"),
      "quantity": 1
    },

    { 
      "first_item": "A",
      "second_item": "A",
      "third_item": "A",
      "price": 1,
      "sales_date": new Date("2018-11-01"),
      "quantity": 1
    },
    { 
      "first_item": "A",
      "second_item": "A",
      "third_item": "A",
      "price": 1,
      "sales_date": new Date("2018-11-02"),
      "quantity": 1
    },
    { 
      "first_item": "A",
      "second_item": "A",
      "third_item": "B",
      "price": 1,
      "sales_date": new Date("2018-10-31"),
      "quantity": 1
    },
    {
     "first_item": "A",
     "second_item": "A",
     "third_item": "B",
     "price": 1,
     "sales_date": new Date("2018-11-03"),
     "quantity": 1
    },
    {
      "first_item": "A",
      "second_item": "B",
      "third_item": "A",
      "price": 1,
      "sales_date": new Date("2018-11-03"),
      "quantity": 1
     },
  ]
},
{
  "_id": 2,
  "data": [
    {
      "first_item": "A",
      "second_item": "A",
      "third_item": "A",
      "price": 2,
      "sales_date": new Date("2018-11-03"),
      "quantity": 1
    },
    { 
      "first_item": "A",
      "second_item": "A",
      "third_item": "A",
      "price": 1,
      "sales_date": new Date("2018-10-31"),
      "quantity": 1
    },
    { 
      "first_item": "A",
      "second_item": "A",
      "third_item": "A",
      "price": 1,
      "sales_date": new Date("2018-11-03"),
      "quantity": 1
    }
  ]
},
{
  "_id": 3,
  "data": [
    {
      "first_item": "A",
      "second_item": "B",
      "third_item": "A",
      "price": 1,
      "sales_date": new Date("2018-11-03"),
      "quantity": 1
     }
  ]
}

Itu semua data yang sama seperti aslinya, namun bukannya bersarang kami sebenarnya hanya memasukkan semuanya ke dalam array datar tunggal di dalam setiap dokumen induk. Tentu ini berarti duplikasi dari berbagai titik data, tetapi perbedaan dalam kompleksitas dan kinerja kueri harus jelas:

db.collection.aggregate([
  { "$match": {
    "data": {
      "$elemMatch": {
        "first_item": "A",
        "second_item": "A",
        "third_item": "A",
        "sales_date": {
          "$gte": new Date("2018-11-01"),
          "$lt": new Date("2018-12-01")
        }
      }
    }
  }},
  { "$addFields": {
    "data": {
      "$filter": {
        "input": "$data",
         "cond": {
           "$and": [
             { "$eq": [ "$$this.first_item", "A" ] },
             { "$eq": [ "$$this.second_item", "A" ] },
             { "$eq": [ "$$this.third_item", "A" ] },
             { "$gte": [ "$$this.sales_date", new Date("2018-11-01") ] },
             { "$lt": [ "$$this.sales_date", new Date("2018-12-01") ] }
           ]
         }
      }
    }
  }},
  { "$unwind": "$data" },
  { "$group": {
    "_id": {
      "date": "$data.sales_date",
      "price": "$data.price",
    },
    "quantity_sold": { "$avg": "$data.quantity" }
  }},
  { "$group": {
    "_id": "$_id.date",
    "prices": {
      "$push": {
        "price": "$_id.price",
        "quantity_sold": "$quantity_sold"
      }
    },
    "quantity_sold": { "$avg": "$quantity_sold" }
  }}
])

Sekarang alih-alih membuat sarang $elemMatch tersebut panggilan dan juga untuk $filter ekspresi, semuanya jauh lebih jelas dan mudah dibaca dan sangat sederhana dalam pemrosesan. Ada keuntungan lain karena Anda sebenarnya bahkan dapat mengindeks kunci elemen dalam array seperti yang digunakan dalam kueri. Itu adalah kendala dari bersarang model di mana MongoDB tidak mengizinkan "Pengindeksan multikey" seperti itu pada kunci array dalam array . Dengan satu larik, ini diperbolehkan dan dapat digunakan untuk meningkatkan kinerja.

Semuanya setelah "pemfilteran konten array" maka tetap sama persis, kecuali hanya nama jalur seperti "data.sales_date" sebagai lawan dari "first_level.second_level.third_level.forth_level.sales_date" yang panjang lebar dari struktur sebelumnya.

Kapan TIDAK Menyematkan

Akhirnya kesalahpahaman besar lainnya adalah bahwa SEMUA Hubungan perlu diterjemahkan sebagai embedding dalam array. Ini benar-benar bukan maksud MongoDB dan Anda hanya dimaksudkan untuk menyimpan data "terkait" dalam dokumen yang sama dalam sebuah larik jika itu berarti melakukan pengambilan data tunggal sebagai lawan dari "bergabung".

Model "Pesanan/Rincian" klasik di sini biasanya berlaku di mana di dunia modern Anda ingin menampilkan "tajuk" untuk "Pesanan" dengan perincian seperti alamat pelanggan, total pesanan, dan sebagainya dalam "layar" yang sama dengan perincian item baris yang berbeda pada "Pesanan".

Jauh di awal RDBMS, 80 karakter dengan 25 layar garis yang khas hanya memiliki informasi "tajuk" seperti itu di satu layar, kemudian garis detail untuk semua yang dibeli ada di layar yang berbeda. Jadi tentu saja ada beberapa tingkat akal sehat untuk menyimpannya di tabel terpisah. Saat dunia bergerak ke lebih detail pada "layar" seperti itu, Anda biasanya ingin melihat semuanya, atau setidaknya "tajuk" dan baris pertama dari "pesanan" semacam itu.

Oleh karena itu mengapa pengaturan semacam ini masuk akal untuk dimasukkan ke dalam array, karena MongoDB mengembalikan "dokumen" yang berisi data terkait sekaligus. Tidak perlu permintaan terpisah untuk layar yang dirender terpisah dan tidak perlu "bergabung" pada data tersebut karena sudah "digabungkan sebelumnya".

Pertimbangkan jika Anda membutuhkannya - AKA "Sepenuhnya" Denormalisasi

Jadi dalam kasus di mana Anda cukup tahu bahwa Anda sebenarnya tidak tertarik untuk berurusan dengan sebagian besar data dalam array seperti itu sebagian besar waktu, biasanya lebih masuk akal untuk meletakkan semuanya dalam satu koleksi sendiri dengan hanya properti lain di untuk mengidentifikasi "induk" jika "penggabungan" seperti itu kadang-kadang diperlukan:

{
  "_id": 1,
  "parent_id": 1,
  "first_item": "A",
  "second_item": "A",
  "third_item": "A",
  "price": 1,
  "sales_date": new Date("2018-10-31"),
  "quantity": 1
},
{ 
  "_id": 2,
  "parent_id": 1,
  "first_item": "A",
  "second_item": "A",
  "third_item": "A",
  "price": 1,
  "sales_date": new Date("2018-11-01"),
  "quantity": 1
},
{ 
  "_id": 3,
  "parent_id": 1,
  "first_item": "A",
  "second_item": "A",
  "third_item": "A",
  "price": 1,
  "sales_date": new Date("2018-11-02"),
  "quantity": 1
},
{ 
  "_id": 4,
  "parent_id": 1,
  "first_item": "A",
  "second_item": "A",
  "third_item": "B",
  "price": 1,
  "sales_date": new Date("2018-10-31"),
  "quantity": 1
},
{
  "_id": 5,
  "parent_id": 1,
  "first_item": "A",
  "second_item": "A",
  "third_item": "B",
  "price": 1,
  "sales_date": new Date("2018-11-03"),
  "quantity": 1
},
{
  "_id": 6,
  "parent_id": 1,
  "first_item": "A",
  "second_item": "B",
  "third_item": "A",
  "price": 1,
  "sales_date": new Date("2018-11-03"),
  "quantity": 1
},
{
  "_id": 7,
  "parent_id": 2,
  "first_item": "A",
  "second_item": "A",
  "third_item": "A",
  "price": 2,
  "sales_date": new Date("2018-11-03"),
  "quantity": 1
},
{ 
  "_id": 8,
  "parent_id": 2,
  "first_item": "A",
  "second_item": "A",
  "third_item": "A",
  "price": 1,
  "sales_date": new Date("2018-10-31"),
  "quantity": 1
},
{ 
  "_id": 9,
  "parent_id": 2,
  "first_item": "A",
  "second_item": "A",
  "third_item": "A",
  "price": 1,
  "sales_date": new Date("2018-11-03"),
  "quantity": 1
},
{
  "_id": 10,
  "parent_id": 3,
  "first_item": "A",
  "second_item": "B",
  "third_item": "A",
  "price": 1,
  "sales_date": new Date("2018-11-03"),
  "quantity": 1
}

Sekali lagi itu adalah data yang sama, tetapi kali ini dalam dokumen yang benar-benar terpisah dengan referensi ke induk paling baik jika Anda mungkin benar-benar membutuhkannya untuk tujuan lain. Perhatikan bahwa agregasi di sini semua tidak berhubungan dengan data induk sama sekali dan juga jelas di mana kinerja tambahan dan kompleksitas yang dihapus masuk hanya dengan menyimpan dalam koleksi terpisah:

db.collection.aggregate([
  { "$match": {
    "first_item": "A",
    "second_item": "A",
    "third_item": "A",
    "sales_date": {
      "$gte": new Date("2018-11-01"),
      "$lt": new Date("2018-12-01")
    }
  }},
  { "$group": {
    "_id": {
      "date": "$sales_date",
      "price": "$price"
    },
    "quantity_sold": { "$avg": "$quantity" }
  }},
  { "$group": {
    "_id": "$_id.date",
    "prices": {
      "$push": {
        "price": "$_id.price",
        "quantity_sold": "$quantity_sold"
      }
    },
    "quantity_sold": { "$avg": "$quantity_sold" }
  }}
])

Karena semuanya sudah menjadi dokumen, tidak perlu "memfilter array" atau memiliki kompleksitas lainnya. Yang Anda lakukan hanyalah memilih dokumen yang cocok dan menggabungkan hasilnya, dengan dua langkah terakhir yang sama persis seperti yang telah ada selama ini.

Untuk tujuan hanya mendapatkan hasil akhir, ini melakukan jauh lebih baik daripada alternatif di atas. Kueri yang dimaksud benar-benar hanya berkaitan dengan data "detail", oleh karena itu tindakan terbaik adalah memisahkan detail dari induknya sepenuhnya karena akan selalu memberikan manfaat kinerja terbaik.

Dan titik keseluruhan di sini adalah di mana pola akses sebenarnya dari sisa aplikasi TIDAK PERNAH perlu mengembalikan seluruh konten array, maka mungkin seharusnya tidak disematkan. Tampaknya sebagian besar operasi "tulis" juga tidak perlu menyentuh induk terkait, dan itu adalah faktor penentu lain di mana ini berfungsi atau tidak.

Kesimpulan

Pesan umum lagi adalah bahwa sebagai aturan umum Anda tidak boleh membuat array bersarang. Paling-paling Anda harus menyimpan larik "tunggal" dengan data yang didenormalisasi sebagian dalam dokumen induk terkait, dan di mana pola akses yang tersisa benar-benar tidak menggunakan induk dan anak secara bersamaan sama sekali, maka data benar-benar harus dipisahkan.

Perubahan "besar" adalah bahwa semua alasan mengapa Anda menganggap normalisasi data sebenarnya baik, ternyata menjadi musuh dari sistem dokumen yang disematkan tersebut. Menghindari "gabungan" selalu baik, tetapi membuat struktur bersarang yang kompleks agar terlihat seperti data "bergabung" juga tidak pernah benar-benar berhasil untuk keuntungan Anda.

Biaya untuk menangani apa yang Anda "pikirkan" adalah normalisasi biasanya berakhir dengan menghabiskan penyimpanan tambahan dan pemeliharaan data yang digandakan dan didenormalisasi dalam penyimpanan terakhir Anda.

Perhatikan juga bahwa semua formulir di atas mengembalikan set hasil yang sama. Ini cukup turunan karena data sampel untuk singkatnya hanya mencakup item tunggal, atau paling banyak di mana ada beberapa titik harga, "rata-rata" masih 1 karena itulah semua nilai. Tapi konten untuk menjelaskan ini sudah sangat panjang jadi itu benar-benar hanya "dengan contoh":

{
        "_id" : ISODate("2018-11-01T00:00:00Z"),
        "prices" : [
                {
                        "price" : 1,
                        "quantity_sold" : 1
                }
        ],
        "quantity_sold" : 1
}
{
        "_id" : ISODate("2018-11-02T00:00:00Z"),
        "prices" : [
                {
                        "price" : 1,
                        "quantity_sold" : 1
                }
        ],
        "quantity_sold" : 1
}
{
        "_id" : ISODate("2018-11-03T00:00:00Z"),
        "prices" : [
                {
                        "price" : 1,
                        "quantity_sold" : 1
                },
                {
                        "price" : 2,
                        "quantity_sold" : 1
                }
        ],
        "quantity_sold" : 1
}



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Set Replika MongoDB yang Terdistribusi Secara Geografis untuk Waktu Aktif 100%

  2. model luwak, array string, array struktur objek

  3. Bagaimana cara memastikan item unik dalam array berdasarkan bidang tertentu - mongoDB?

  4. Nilai waktu tanggal MongoDB tidak disimpan dengan benar

  5. NotUniqueError:Mencoba menyimpan duplikat kunci unik