Bagaimana cara menemukan skema koleksi di mongodb?

Pada intinya, aplikasi web menawarkan kepada penggunanya tampilan ke dalam, dan cara untuk memodifikasi, kumpulan data yang persisten. Apakah mengelola daftar todos, atau memesan mobil untuk menjemput Anda, Anda berinteraksi dengan lapisan data yang permanen namun terus berubah

Di Meteor, lapisan data tersebut biasanya disimpan di MongoDB. Satu set data terkait di MongoDB disebut sebagai "kumpulan". Di Meteor Anda mengakses MongoDB melalui , menjadikannya mekanisme persistensi utama untuk data aplikasi Anda

Namun, koleksi lebih dari sekadar cara untuk menyimpan dan mengambil data. Mereka juga memberikan inti dari pengalaman pengguna yang interaktif dan terhubung yang diharapkan pengguna dari aplikasi terbaik. Meteor membuat pengalaman pengguna ini mudah diterapkan

Dalam artikel ini, kita akan mencermati cara kerja koleksi di berbagai tempat dalam kerangka kerja, dan cara memanfaatkannya secara maksimal

Koleksi sisi server

Saat Anda membuat koleksi di server

Todos = new Mongo.Collection('todos');

Anda membuat koleksi di dalam MongoDB, dan antarmuka ke koleksi tersebut untuk digunakan di server. Ini adalah lapisan yang cukup mudah di atas driver Node MongoDB yang mendasarinya, tetapi dengan API sinkron

// This line won't complete until the insert is done
Todos.insert({_id: 'my-todo'});
// So this line will return something
const todo = Todos.findOne({_id: 'my-todo'});
// Look ma, no callbacks!
console.log(todo);
_

Koleksi sisi klien

Di klien, saat Anda menulis baris yang sama

Todos = new Mongo.Collection('todos');

Itu melakukan sesuatu yang sama sekali berbeda

Pada klien, tidak ada koneksi langsung ke database MongoDB, dan sebenarnya API sinkron untuk itu tidak mungkin (atau mungkin yang Anda inginkan). Sebagai gantinya, pada klien, koleksi adalah cache sisi klien dari database. Hal ini dicapai berkat perpustakaan Minimongo—sebuah implementasi dalam memori, semua JS, dari MongoDB API

// This line is changing an in-memory Minimongo data structure
Todos.insert({_id: 'my-todo'});
// And this line is querying it
const todo = Todos.findOne({_id: 'my-todo'});
// So this happens right away!
console.log(todo);

Cara Anda memindahkan data dari koleksi server (dan yang didukung MongoDB) ke koleksi klien (dalam memori) adalah subjek dari artikel pemuatan data. Secara umum, Anda berlangganan publikasi, yang mendorong data dari server ke klien. Biasanya, Anda dapat berasumsi bahwa klien berisi salinan terbaru dari beberapa subset dari koleksi lengkap MongoDB

Untuk menulis data kembali ke server, Anda menggunakan Metode, subjek dari artikel metode

Koleksi lokal

Ada cara ketiga untuk menggunakan koleksi di Meteor. Di klien atau server, jika Anda membuat koleksi dengan salah satu dari dua cara ini

SelectedTodos = new Mongo.Collection(null);
SelectedTodos = new Mongo.Collection('selectedtodos', {connection: null});
_

Ini menciptakan koleksi lokal. Ini adalah koleksi Minimongo yang tidak memiliki koneksi database (biasanya koleksi akan terhubung langsung ke database di server, atau melalui langganan di klien)

Koleksi lokal adalah cara mudah untuk menggunakan kekuatan penuh perpustakaan Minimongo untuk penyimpanan dalam memori. Misalnya, Anda mungkin menggunakannya sebagai pengganti larik sederhana jika Anda perlu menjalankan kueri kompleks atas data Anda. Atau Anda mungkin ingin memanfaatkan reaktivitasnya pada klien untuk mendorong beberapa UI dengan cara yang terasa alami di Meteor

Mendefinisikan skema

Meskipun MongoDB adalah database tanpa skema, yang memungkinkan fleksibilitas maksimum dalam penataan data, umumnya praktik yang baik menggunakan skema untuk membatasi konten koleksi Anda agar sesuai dengan format yang diketahui. Jika tidak, maka Anda cenderung perlu menulis kode defensif untuk memeriksa dan mengonfirmasi struktur data Anda saat keluar dari database, bukan saat masuk ke database. Seperti dalam kebanyakan hal, Anda cenderung membaca data lebih sering daripada menulisnya, sehingga biasanya lebih mudah, dan lebih sedikit buggy untuk menggunakan skema saat menulis

Di Meteor, paket skema unggulan adalah paket npm simpl-schema. Ini adalah skema ekspresif berbasis MongoDB yang digunakan untuk menyisipkan dan memperbarui dokumen. Alternatif lain adalah jagi. astronomi yang merupakan lapisan Object Model (OM) lengkap yang menawarkan definisi skema, validator sisi server/klien, metode objek, dan penangan peristiwa

Anggaplah kita memiliki koleksi

Todos = new Mongo.Collection('todos');
5. Untuk menentukan skema untuk koleksi ini menggunakan
Todos = new Mongo.Collection('todos');
_6, Anda dapat membuat instance baru dari kelas
Todos = new Mongo.Collection('todos');
7 dan melampirkannya ke objek
Todos = new Mongo.Collection('todos');
5

import SimpleSchema from 'simpl-schema';

Lists.schema = new SimpleSchema({
  name: {type: String},
  incompleteCount: {type: Number, defaultValue: 0},
  userId: {type: String, regEx: SimpleSchema.RegEx.Id, optional: true}
});
_

Contoh dari aplikasi Todos ini mendefinisikan skema dengan beberapa aturan sederhana

  1. Kami menentukan bahwa bidang
    Todos = new Mongo.Collection('todos');
    
    _9 dari daftar diperlukan dan harus berupa string
  2. Kami menentukan
    // This line is changing an in-memory Minimongo data structure
    Todos.insert({_id: 'my-todo'});
    // And this line is querying it
    const todo = Todos.findOne({_id: 'my-todo'});
    // So this happens right away!
    console.log(todo);
    
    _0 adalah angka, yang pada penyisipan diatur ke
    // This line is changing an in-memory Minimongo data structure
    Todos.insert({_id: 'my-todo'});
    // And this line is querying it
    const todo = Todos.findOne({_id: 'my-todo'});
    // So this happens right away!
    console.log(todo);
    
    1 jika tidak ditentukan lain
  3. Kami menetapkan bahwa
    // This line is changing an in-memory Minimongo data structure
    Todos.insert({_id: 'my-todo'});
    // And this line is querying it
    const todo = Todos.findOne({_id: 'my-todo'});
    // So this happens right away!
    console.log(todo);
    
    _2, yang bersifat opsional, harus berupa string yang terlihat seperti ID dokumen pengguna

Kami melampirkan skema ke namespace

Todos = new Mongo.Collection('todos');
5 secara langsung, yang memungkinkan kami untuk memeriksa objek terhadap skema ini secara langsung kapan pun kami mau, seperti dalam bentuk atau Metode. Di bagian ini kita akan melihat cara menggunakan skema ini secara otomatis saat menulis ke koleksi

Anda dapat melihat bahwa dengan kode yang relatif sedikit, kami berhasil membatasi format daftar secara signifikan. Anda dapat membaca lebih lanjut tentang hal-hal yang lebih rumit yang dapat dilakukan dengan skema di dokumen Skema Sederhana

Memvalidasi terhadap skema

Sekarang kami memiliki skema, bagaimana kami menggunakannya?

Cukup mudah untuk memvalidasi dokumen dengan skema. Kita bisa menulis

const list = {
  name: 'My list',
  incompleteCount: 3
};

Lists.schema.validate(list);

Dalam hal ini, karena daftar valid menurut skema, baris

// This line is changing an in-memory Minimongo data structure
Todos.insert({_id: 'my-todo'});
// And this line is querying it
const todo = Todos.findOne({_id: 'my-todo'});
// So this happens right away!
console.log(todo);
4 akan berjalan tanpa masalah. Namun jika, kami menulis

const list = {
  name: 'My list',
  incompleteCount: 3,
  madeUpField: 'this should not be here'
};

Lists.schema.validate(list);

Kemudian panggilan

// This line is changing an in-memory Minimongo data structure
Todos.insert({_id: 'my-todo'});
// And this line is querying it
const todo = Todos.findOne({_id: 'my-todo'});
// So this happens right away!
console.log(todo);
_4 akan memunculkan
// This line is changing an in-memory Minimongo data structure
Todos.insert({_id: 'my-todo'});
// And this line is querying it
const todo = Todos.findOne({_id: 'my-todo'});
// So this happens right away!
console.log(todo);
6 yang berisi perincian tentang apa yang salah dengan dokumen
// This line is changing an in-memory Minimongo data structure
Todos.insert({_id: 'my-todo'});
// And this line is querying it
const todo = Todos.findOne({_id: 'my-todo'});
// So this happens right away!
console.log(todo);
7

`ValidationError`

Apa itu

// This line is changing an in-memory Minimongo data structure
Todos.insert({_id: 'my-todo'});
// And this line is querying it
const todo = Todos.findOne({_id: 'my-todo'});
// So this happens right away!
console.log(todo);
_6? . Biasanya, detail pada
// This line is changing an in-memory Minimongo data structure
Todos.insert({_id: 'my-todo'});
// And this line is querying it
const todo = Todos.findOne({_id: 'my-todo'});
// So this happens right away!
console.log(todo);
_6 digunakan untuk menandai formulir dengan informasi tentang input yang tidak cocok dengan skema. Di , kita akan melihat lebih banyak tentang cara kerjanya

Merancang skema data Anda

Sekarang setelah Anda terbiasa dengan API dasar Skema Sederhana, ada baiknya mempertimbangkan beberapa batasan sistem data Meteor yang dapat memengaruhi desain skema data Anda. Meskipun secara umum Anda dapat membuat skema data Meteor seperti skema data MongoDB lainnya, ada beberapa detail penting yang perlu diingat

Pertimbangan terpenting terkait dengan cara DDP, protokol pemuatan data Meteor, mengkomunikasikan dokumen melalui kabel. Hal utama yang harus disadari adalah bahwa DDP mengirimkan perubahan ke dokumen di tingkat bidang dokumen tingkat atas. Artinya, jika Anda memiliki subbidang yang besar dan kompleks pada dokumen yang sering berubah, DDP dapat mengirim perubahan yang tidak perlu melalui kabel

Misalnya, dalam MongoDB "murni" Anda dapat merancang skema sehingga setiap dokumen daftar memiliki bidang bernama

SelectedTodos = new Mongo.Collection(null);
SelectedTodos = new Mongo.Collection('selectedtodos', {connection: null});
0 yang merupakan larik item todo

Lists.schema = new SimpleSchema({
  name: {type: String},
  todos: {type: [Object]}
});

Masalah dengan skema ini adalah karena perilaku DDP yang baru saja disebutkan, setiap perubahan pada item todo apa pun dalam daftar akan memerlukan pengiriman seluruh rangkaian todo untuk daftar itu melalui jaringan. Ini karena DDP tidak memiliki konsep "ubah bidang

SelectedTodos = new Mongo.Collection(null);
SelectedTodos = new Mongo.Collection('selectedtodos', {connection: null});
1 dari item ke-3 di bidang yang disebut
SelectedTodos = new Mongo.Collection(null);
SelectedTodos = new Mongo.Collection('selectedtodos', {connection: null});
0". Itu hanya dapat "mengubah bidang yang disebut
SelectedTodos = new Mongo.Collection(null);
SelectedTodos = new Mongo.Collection('selectedtodos', {connection: null});
0 ke array yang benar-benar baru"

Denormalisasi dan banyak koleksi

Implikasi dari hal di atas adalah kita perlu membuat lebih banyak koleksi untuk memuat sub-dokumen. Dalam kasus aplikasi Todos, kami membutuhkan koleksi

Todos = new Mongo.Collection('todos');
5 dan koleksi
SelectedTodos = new Mongo.Collection(null);
SelectedTodos = new Mongo.Collection('selectedtodos', {connection: null});
5 untuk memuat setiap daftar item todo. Oleh karena itu, kami perlu melakukan beberapa hal yang biasanya Anda kaitkan dengan database SQL, seperti menggunakan kunci asing (
SelectedTodos = new Mongo.Collection(null);
SelectedTodos = new Mongo.Collection('selectedtodos', {connection: null});
6) untuk mengaitkan satu dokumen dengan dokumen lainnya

Di Meteor, sering kali melakukan hal ini lebih sedikit masalah daripada di aplikasi MongoDB pada umumnya, karena mudah untuk menerbitkan kumpulan dokumen yang tumpang tindih (kita mungkin memerlukan satu kumpulan pengguna untuk merender satu layar aplikasi kita, dan kumpulan yang berpotongan . Jadi dalam skenario itu ada keuntungan memisahkan subdokumen dari induknya

Namun, mengingat MongoDB sebelum versi 3. 2 tidak mendukung kueri pada banyak koleksi ("bergabung"), kami biasanya harus mendenormalisasi beberapa data kembali ke koleksi induk. Denormalisasi adalah praktik menyimpan potongan informasi yang sama dalam database berkali-kali (berlawanan dengan bentuk "normal" yang tidak berlebihan). MongoDB adalah database tempat denormalisasi didorong, dan dengan demikian dioptimalkan untuk praktik ini

Dalam kasus aplikasi Todos, karena kami ingin menampilkan jumlah todos yang belum selesai di sebelah setiap daftar, kami perlu melakukan denormalisasi

SelectedTodos = new Mongo.Collection(null);
SelectedTodos = new Mongo.Collection('selectedtodos', {connection: null});
7. Ini adalah ketidaknyamanan tetapi biasanya cukup mudah dilakukan seperti yang akan kita lihat di bagian di bawah ini

Denormalisasi lain yang terkadang diperlukan oleh arsitektur ini dapat berasal dari dokumen induk ke sub-dokumen. Misalnya, di Todos, karena kami menegakkan privasi daftar todo melalui atribut

SelectedTodos = new Mongo.Collection(null);
SelectedTodos = new Mongo.Collection('selectedtodos', {connection: null});
8, tetapi kami menerbitkan todos secara terpisah, mungkin masuk akal untuk mendenormalisasi
SelectedTodos = new Mongo.Collection(null);
SelectedTodos = new Mongo.Collection('selectedtodos', {connection: null});
9 juga. Untuk melakukan ini, kita harus berhati-hati untuk mengambil
// This line is changing an in-memory Minimongo data structure
Todos.insert({_id: 'my-todo'});
// And this line is querying it
const todo = Todos.findOne({_id: 'my-todo'});
// So this happens right away!
console.log(todo);
2 dari daftar saat membuat todo, dan memperbarui semua todo yang relevan setiap kali daftar
// This line is changing an in-memory Minimongo data structure
Todos.insert({_id: 'my-todo'});
// And this line is querying it
const todo = Todos.findOne({_id: 'my-todo'});
// So this happens right away!
console.log(todo);
2 berubah

Merancang untuk masa depan

Aplikasi, terutama aplikasi web, jarang selesai, dan sangat berguna untuk mempertimbangkan potensi perubahan di masa mendatang saat mendesain skema data Anda. Seperti dalam kebanyakan hal, menambahkan bidang jarang merupakan ide yang baik sebelum Anda benar-benar membutuhkannya (seringkali apa yang Anda perkirakan tidak benar-benar terjadi pada akhirnya)

Namun, sebaiknya pikirkan terlebih dahulu bagaimana skema dapat berubah seiring waktu. Misalnya, Anda mungkin memiliki daftar string pada dokumen (mungkin sekumpulan tag). Meskipun tergoda untuk membiarkannya sebagai subbidang pada dokumen (dengan asumsi mereka tidak banyak berubah), jika ada kemungkinan besar mereka akan menjadi lebih rumit di masa mendatang (mungkin tag akan memiliki pembuat, atau subtag nanti

Jumlah pandangan jauh ke depan yang Anda masukkan ke dalam desain skema Anda akan bergantung pada batasan individual aplikasi Anda, dan perlu menjadi keputusan penilaian di pihak Anda

Menggunakan skema saat menulis

Meskipun ada berbagai cara untuk menjalankan data melalui Skema Sederhana sebelum mengirimkannya ke koleksi Anda (misalnya Anda dapat memeriksa skema di setiap pemanggilan metode), yang paling sederhana dan paling dapat diandalkan adalah menggunakan paket

import SimpleSchema from 'simpl-schema';

Lists.schema = new SimpleSchema({
  name: {type: String},
  incompleteCount: {type: Number, defaultValue: 0},
  userId: {type: String, regEx: SimpleSchema.RegEx.Id, optional: true}
});
2 untuk menjalankan setiap

Untuk melakukannya, kami menggunakan

import SimpleSchema from 'simpl-schema';

Lists.schema = new SimpleSchema({
  name: {type: String},
  incompleteCount: {type: Number, defaultValue: 0},
  userId: {type: String, regEx: SimpleSchema.RegEx.Id, optional: true}
});
_4

Lists.attachSchema(Lists.schema);

Artinya, sekarang setiap kali kita memanggil

import SimpleSchema from 'simpl-schema';

Lists.schema = new SimpleSchema({
  name: {type: String},
  incompleteCount: {type: Number, defaultValue: 0},
  userId: {type: String, regEx: SimpleSchema.RegEx.Id, optional: true}
});
5,
import SimpleSchema from 'simpl-schema';

Lists.schema = new SimpleSchema({
  name: {type: String},
  incompleteCount: {type: Number, defaultValue: 0},
  userId: {type: String, regEx: SimpleSchema.RegEx.Id, optional: true}
});
6,
import SimpleSchema from 'simpl-schema';

Lists.schema = new SimpleSchema({
  name: {type: String},
  incompleteCount: {type: Number, defaultValue: 0},
  userId: {type: String, regEx: SimpleSchema.RegEx.Id, optional: true}
});
7, pertama-tama dokumen atau pengubah kita akan diperiksa secara otomatis terhadap skema (dengan cara yang sedikit berbeda tergantung pada mutator yang tepat)

`defaultValue` dan pembersihan data

Satu hal yang dilakukan Collection2 adalah sebelum mengirimkannya ke database. Ini termasuk tetapi tidak terbatas pada

  1. Jenis pemaksaan - mengubah string menjadi angka
  2. Menghapus atribut yang tidak ada dalam skema
  3. Menetapkan nilai default berdasarkan
    import SimpleSchema from 'simpl-schema';
    
    Lists.schema = new SimpleSchema({
      name: {type: String},
      incompleteCount: {type: Number, defaultValue: 0},
      userId: {type: String, regEx: SimpleSchema.RegEx.Id, optional: true}
    });
    
    _8 dalam definisi skema

Namun, terkadang berguna untuk melakukan inisialisasi yang lebih rumit ke dokumen sebelum memasukkannya ke dalam koleksi. Misalnya, di aplikasi Todos, kami ingin menyetel nama daftar baru menjadi

import SimpleSchema from 'simpl-schema';

Lists.schema = new SimpleSchema({
  name: {type: String},
  incompleteCount: {type: Number, defaultValue: 0},
  userId: {type: String, regEx: SimpleSchema.RegEx.Id, optional: true}
});
9 di mana
const list = {
  name: 'My list',
  incompleteCount: 3
};

Lists.schema.validate(list);
0 adalah huruf unik berikutnya yang tersedia

Untuk melakukannya, kita dapat membuat subkelas

const list = {
  name: 'My list',
  incompleteCount: 3
};

Lists.schema.validate(list);
1 dan menulis metode
const list = {
  name: 'My list',
  incompleteCount: 3
};

Lists.schema.validate(list);
2 kita sendiri

// This line won't complete until the insert is done
Todos.insert({_id: 'my-todo'});
// So this line will return something
const todo = Todos.findOne({_id: 'my-todo'});
// Look ma, no callbacks!
console.log(todo);
_0

Kait saat menyisipkan/memperbarui/menghapus

Teknik di atas juga dapat digunakan untuk menyediakan lokasi untuk "menghubungkan" fungsionalitas ekstra ke dalam koleksi. Misalnya, saat menghapus daftar, kami selalu ingin menghapus semua todo-nya secara bersamaan

Kita juga dapat menggunakan subkelas untuk kasus ini, menggantikan metode

const list = {
  name: 'My list',
  incompleteCount: 3
};

Lists.schema.validate(list);
3

// This line won't complete until the insert is done
Todos.insert({_id: 'my-todo'});
// So this line will return something
const todo = Todos.findOne({_id: 'my-todo'});
// Look ma, no callbacks!
console.log(todo);
_1

Teknik ini memiliki beberapa kelemahan

  1. Mutator bisa menjadi sangat lama ketika Anda ingin melakukan hook berkali-kali
  2. Terkadang satu fungsi dapat tersebar di beberapa mutator
  3. Ini bisa menjadi tantangan untuk menulis hook dengan cara yang sepenuhnya umum (yang mencakup setiap kemungkinan pemilih dan pengubah), dan mungkin tidak diperlukan untuk aplikasi Anda (karena mungkin Anda hanya pernah memanggil mutator itu dengan satu cara)

Cara mengatasi poin 1. dan 2. adalah memisahkan kumpulan kait ke dalam modulnya sendiri, dan menggunakan mutator sebagai titik untuk memanggil modul itu dengan cara yang masuk akal. Kita akan melihat contohnya

Poin 3. biasanya dapat diselesaikan dengan menempatkan hook di Metode yang memanggil mutator, bukan di hook itu sendiri. Meskipun ini adalah kompromi yang tidak sempurna (karena kita perlu berhati-hati jika kita menambahkan Metode lain yang memanggil mutator itu di masa mendatang), ini lebih baik daripada menulis sekumpulan kode yang tidak pernah benar-benar dipanggil (yang dijamin tidak akan berfungsi. ), atau memberi kesan bahwa hook Anda lebih umum dari yang sebenarnya

Mengabstraksi denormalizer

Denormalisasi mungkin perlu terjadi pada berbagai mutator dari beberapa koleksi. Oleh karena itu, masuk akal untuk mendefinisikan logika denormalisasi di satu tempat, dan menghubungkannya ke setiap mutator dengan satu baris kode. Keuntungan dari pendekatan ini adalah logika denormalisasi berada di satu tempat daripada tersebar di banyak file, tetapi Anda masih dapat memeriksa kode untuk setiap kumpulan dan memahami sepenuhnya apa yang terjadi pada setiap pembaruan

Dalam aplikasi contoh Todos, kami membuat

const list = {
  name: 'My list',
  incompleteCount: 3
};

Lists.schema.validate(list);
4 untuk mengabstraksi penghitungan todos yang tidak lengkap pada daftar. Kode ini perlu dijalankan setiap kali item todo dimasukkan, diperbarui (dicentang atau tidak), atau dihapus. Kodenya terlihat seperti

// This line won't complete until the insert is done
Todos.insert({_id: 'my-todo'});
// So this line will return something
const todo = Todos.findOne({_id: 'my-todo'});
// Look ma, no callbacks!
console.log(todo);
_2

Kami kemudian dapat menghubungkan denormalizer ke dalam mutasi koleksi

SelectedTodos = new Mongo.Collection(null);
SelectedTodos = new Mongo.Collection('selectedtodos', {connection: null});
5 seperti itu

// This line won't complete until the insert is done
Todos.insert({_id: 'my-todo'});
// So this line will return something
const todo = Todos.findOne({_id: 'my-todo'});
// Look ma, no callbacks!
console.log(todo);
_3

Perhatikan bahwa kami hanya menangani mutator yang benar-benar kami gunakan dalam aplikasi—kami tidak berurusan dengan semua cara yang memungkinkan jumlah todo pada daftar dapat berubah. Misalnya, jika Anda mengubah

const list = {
  name: 'My list',
  incompleteCount: 3
};

Lists.schema.validate(list);
_6 pada item todo, Anda perlu mengubah
// This line is changing an in-memory Minimongo data structure
Todos.insert({_id: 'my-todo'});
// And this line is querying it
const todo = Todos.findOne({_id: 'my-todo'});
// So this happens right away!
console.log(todo);
0 dari dua daftar. Namun, karena aplikasi kami tidak melakukan ini, kami tidak menanganinya di denormalizer

Berurusan dengan setiap kemungkinan operator MongoDB sulit dilakukan dengan benar, karena MongoDB memiliki bahasa pengubah yang kaya. Alih-alih, kami fokus menangani pengubah yang kami tahu akan kami lihat di aplikasi kami. Jika ini menjadi terlalu rumit, maka memindahkan pengait untuk logika ke dalam Metode yang benar-benar membuat modifikasi yang relevan bisa masuk akal (walaupun Anda harus rajin memastikan Anda melakukannya di semua tempat yang relevan, baik sekarang maupun saat aplikasi berubah

Mungkin masuk akal jika ada paket untuk sepenuhnya mengabstraksi beberapa teknik denormalisasi umum dan benar-benar berusaha menangani semua kemungkinan modifikasi. Jika Anda menulis paket seperti itu, beri tahu kami

Bermigrasi ke skema baru

Seperti yang telah kita bahas di atas, mencoba memprediksi semua persyaratan skema data Anda di masa mendatang adalah hal yang mustahil. Tak pelak, saat sebuah proyek matang, akan tiba saatnya Anda perlu mengubah skema database. Anda harus berhati-hati tentang cara melakukan migrasi ke skema baru untuk memastikan aplikasi Anda bekerja dengan lancar selama dan setelah migrasi

Paket yang berguna untuk menulis migrasi adalah

const list = {
  name: 'My list',
  incompleteCount: 3
};

Lists.schema.validate(list);
8, yang menyediakan kerangka kerja bagus untuk beralih di antara berbagai versi skema Anda

Misalkan, sebagai contoh, kami ingin menambahkan bidang

const list = {
  name: 'My list',
  incompleteCount: 3
};

Lists.schema.validate(list);
9, dan memastikan bahwa bidang itu ditetapkan untuk semua daftar yang ada. Kemudian kita dapat menulis yang berikut dalam kode khusus server (mis. g.
const list = {
  name: 'My list',
  incompleteCount: 3,
  madeUpField: 'this should not be here'
};

Lists.schema.validate(list);
_0)

// This line won't complete until the insert is done
Todos.insert({_id: 'my-todo'});
// So this line will return something
const todo = Todos.findOne({_id: 'my-todo'});
// Look ma, no callbacks!
console.log(todo);
_4

Migrasi ini, yang diurutkan menjadi migrasi pertama yang berjalan di atas database, akan, saat dipanggil, memperbarui setiap daftar dengan hitungan todo saat ini

Untuk mengetahui lebih lanjut tentang API dari paket Migrasi, lihat dokumentasinya

Perubahan massal

Jika migrasi Anda perlu mengubah banyak data, dan terutama jika Anda perlu menghentikan server aplikasi Anda saat sedang berjalan, sebaiknya gunakan Operasi Massal MongoDB

Keuntungan dari operasi massal adalah hanya memerlukan satu perjalanan pulang pergi ke MongoDB untuk penulisan, yang biasanya berarti jauh lebih cepat. Sisi negatifnya adalah jika migrasi Anda rumit (yang biasanya terjadi jika Anda tidak dapat melakukan

const list = {
  name: 'My list',
  incompleteCount: 3,
  madeUpField: 'this should not be here'
};

Lists.schema.validate(list);
1), diperlukan banyak waktu untuk menyiapkan pembaruan massal

Artinya, jika pengguna mengakses situs saat pembaruan sedang disiapkan, kemungkinan besar situs tersebut tidak akan berfungsi. Selain itu, pembaruan massal akan mengunci seluruh koleksi saat sedang diterapkan, yang dapat menyebabkan blip yang signifikan dalam pengalaman pengguna Anda jika perlu beberapa saat. Karena alasan ini, Anda sering kali harus menghentikan server dan memberi tahu pengguna bahwa Anda sedang melakukan pemeliharaan saat pembaruan sedang berlangsung

Kami dapat menulis migrasi kami di atas seperti itu (perhatikan bahwa Anda harus menggunakan MongoDB 2. 6 atau lebih baru agar operasi pembaruan massal ada). Kami dapat mengakses API MongoDB asli melalui

// This line won't complete until the insert is done
Todos.insert({_id: 'my-todo'});
// So this line will return something
const todo = Todos.findOne({_id: 'my-todo'});
// Look ma, no callbacks!
console.log(todo);
_5

Perhatikan bahwa kami dapat membuat migrasi ini lebih cepat dengan menggunakan Agregasi untuk mengumpulkan kumpulan awal jumlah todo

Menjalankan migrasi

Untuk menjalankan migrasi terhadap database pengembangan Anda, paling mudah menggunakan shell Meteor

// This line won't complete until the insert is done
Todos.insert({_id: 'my-todo'});
// So this line will return something
const todo = Todos.findOne({_id: 'my-todo'});
// Look ma, no callbacks!
console.log(todo);
_6

Jika migrasi mencatat apa pun ke konsol, Anda akan melihatnya di jendela terminal yang menjalankan server Meteor

Untuk menjalankan migrasi terhadap basis data produksi Anda, jalankan aplikasi Anda secara lokal dalam mode produksi (dengan setelan produksi dan variabel lingkungan, termasuk setelan basis data), dan gunakan shell Meteor dengan cara yang sama. Apa yang dilakukan adalah menjalankan fungsi

const list = {
  name: 'My list',
  incompleteCount: 3,
  madeUpField: 'this should not be here'
};

Lists.schema.validate(list);
_3 dari semua migrasi yang belum selesai, terhadap basis data produksi Anda. Dalam kasus kami, ini harus memastikan semua daftar memiliki kumpulan bidang
const list = {
  name: 'My list',
  incompleteCount: 3,
  madeUpField: 'this should not be here'
};

Lists.schema.validate(list);
4

Cara yang baik untuk melakukan hal di atas adalah dengan menjalankan mesin virtual yang dekat dengan database Anda yang telah menginstal Meteor dan akses SSH (instance EC2 khusus yang Anda mulai dan hentikan untuk tujuan tersebut adalah opsi yang masuk akal), dan menjalankan perintah setelah penembakan . Dengan begitu latensi apa pun antara mesin Anda dan database akan dihilangkan, tetapi Anda masih bisa sangat berhati-hati tentang cara menjalankan migrasi

Perhatikan bahwa Anda harus selalu membuat cadangan basis data sebelum menjalankan migrasi apa pun

Melanggar perubahan skema

Terkadang saat kami mengubah skema aplikasi, kami melakukannya dengan cara yang melanggar – sehingga skema lama tidak berfungsi dengan baik dengan basis kode baru. Misalnya, jika kita memiliki beberapa kode UI yang sangat bergantung pada semua daftar yang memiliki

const list = {
  name: 'My list',
  incompleteCount: 3,
  madeUpField: 'this should not be here'
};

Lists.schema.validate(list);
4, akan ada periode, sebelum migrasi berjalan, di mana UI aplikasi kita akan rusak setelah kita menerapkan

Cara sederhana untuk mengatasi masalah ini adalah dengan menghentikan aplikasi selama periode antara penerapan dan penyelesaian migrasi. Ini jauh dari ideal, terutama mengingat beberapa migrasi dapat memakan waktu berjam-jam untuk dijalankan (walaupun menggunakan mungkin sangat membantu di sini)

Pendekatan yang lebih baik adalah penyebaran multi-tahap. Ide dasarnya adalah itu

  1. Terapkan versi aplikasi Anda yang dapat menangani skema lama dan baru. Dalam kasus kami, ini akan menjadi kode yang tidak mengharapkan
    const list = {
      name: 'My list',
      incompleteCount: 3,
      madeUpField: 'this should not be here'
    };
    
    Lists.schema.validate(list);
    
    4 ada di sana, tetapi memperbaruinya dengan benar saat todo baru dibuat
  2. Jalankan migrasi. Pada titik ini Anda harus yakin bahwa semua daftar memiliki
    const list = {
      name: 'My list',
      incompleteCount: 3,
      madeUpField: 'this should not be here'
    };
    
    Lists.schema.validate(list);
    
    4
  3. Terapkan kode baru yang bergantung pada skema baru dan tidak lagi mengetahui cara menangani skema lama. Sekarang kami aman untuk mengandalkan
    const list = {
      name: 'My list',
      incompleteCount: 3
    };
    
    Lists.schema.validate(list);
    
    _9 di UI kami

Hal lain yang harus diperhatikan, terutama dengan penyebaran multi-tahap seperti itu, adalah penting untuk bersiap untuk melakukan rollback. Untuk alasan ini, paket migrasi memungkinkan Anda menentukan fungsi

const list = {
  name: 'My list',
  incompleteCount: 3,
  madeUpField: 'this should not be here'
};

Lists.schema.validate(list);
9 dan memanggil
Lists.schema = new SimpleSchema({
  name: {type: String},
  todos: {type: [Object]}
});
0 untuk bermigrasi kembali ke versi
Lists.schema = new SimpleSchema({
  name: {type: String},
  todos: {type: [Object]}
});
1

Jadi jika kami ingin membalikkan migrasi kami di atas, kami akan lari

// This line won't complete until the insert is done
Todos.insert({_id: 'my-todo'});
// So this line will return something
const todo = Todos.findOne({_id: 'my-todo'});
// Look ma, no callbacks!
console.log(todo);
_7

Jika Anda merasa perlu mengembalikan versi kode Anda, Anda harus berhati-hati dengan datanya, dan melangkah dengan hati-hati melalui langkah-langkah penerapan Anda secara terbalik

Peringatan

Beberapa aspek dari strategi migrasi yang diuraikan di atas mungkin bukan cara yang paling ideal untuk melakukan sesuatu (walaupun mungkin sesuai dalam banyak situasi). Berikut adalah beberapa hal lain yang perlu diperhatikan

  1. Biasanya lebih baik tidak mengandalkan kode aplikasi Anda dalam migrasi (karena aplikasi akan berubah seiring waktu, dan migrasi seharusnya tidak). Misalnya, membuat migrasi Anda melewati koleksi Collection2 Anda (dan dengan demikian memeriksa skema, menyetel nilai otomatis, dll.) kemungkinan akan merusaknya seiring waktu karena skema Anda berubah seiring waktu.

    Salah satu cara untuk menghindari masalah ini adalah dengan tidak menjalankan migrasi lama di database Anda. Ini sedikit membatasi tetapi dapat dibuat untuk bekerja

  2. Menjalankan migrasi di mesin lokal Anda mungkin akan memakan waktu lebih lama karena mesin Anda tidak sedekat mungkin dengan database produksi

Menyebarkan "aplikasi migrasi" khusus ke perangkat keras yang sama dengan aplikasi Anda yang sebenarnya mungkin merupakan cara terbaik untuk menyelesaikan masalah di atas. Akan luar biasa jika aplikasi semacam itu melacak migrasi mana yang berjalan, dengan log dan menyediakan UI untuk memeriksa dan menjalankannya. Mungkin aplikasi boilerplate untuk melakukannya dapat dibuat (jika Anda melakukannya, beri tahu kami dan kami akan menautkannya di sini. )

Asosiasi antara koleksi

Seperti yang telah kita bahas sebelumnya, sangat umum dalam aplikasi Meteor untuk memiliki asosiasi antar dokumen dalam koleksi yang berbeda. Akibatnya, sangat umum juga untuk menulis kueri yang mengambil dokumen terkait setelah Anda memiliki dokumen yang Anda minati (misalnya semua todo yang ada dalam satu daftar)

Untuk membuatnya lebih mudah, kita dapat melampirkan fungsi ke prototipe dokumen milik koleksi tertentu, untuk memberi kita "metode" pada dokumen (dalam pengertian berorientasi objek). Kami kemudian dapat menggunakan metode ini untuk membuat kueri baru untuk menemukan dokumen terkait

Untuk membuatnya lebih mudah, kita dapat menggunakan paket

Lists.schema = new SimpleSchema({
  name: {type: String},
  todos: {type: [Object]}
});
2 untuk mengaitkan koleksi dan mengambil relasinya. Sebagai contoh

// This line won't complete until the insert is done
Todos.insert({_id: 'my-todo'});
// So this line will return something
const todo = Todos.findOne({_id: 'my-todo'});
// Look ma, no callbacks!
console.log(todo);
_8

Ini memungkinkan kami untuk mengambil daftar dengan benar beserta todo-nya

// This line won't complete until the insert is done
Todos.insert({_id: 'my-todo'});
// So this line will return something
const todo = Todos.findOne({_id: 'my-todo'});
// Look ma, no callbacks!
console.log(todo);
_9

Lists.schema = new SimpleSchema({
  name: {type: String},
  todos: {type: [Object]}
});
3 akan terlihat seperti ini

Todos = new Mongo.Collection('todos');
0

Grapher mendukung kueri isomorfik (reaktif dan non-reaktif), memiliki fitur keamanan bawaan, bekerja dengan banyak jenis hubungan, dan banyak lagi. Lihat dokumentasi Grapher untuk detail lebih lanjut

Pembantu koleksi

Kita dapat menggunakan paket

Lists.schema = new SimpleSchema({
  name: {type: String},
  todos: {type: [Object]}
});
4 untuk dengan mudah melampirkan metode tersebut (atau "pembantu") ke dokumen. Contohnya

Todos = new Mongo.Collection('todos');
_1

Setelah kami melampirkan pembantu ini ke koleksi

Todos = new Mongo.Collection('todos');
5, setiap kali kami mengambil daftar dari database (di klien atau server), fungsi
Lists.schema = new SimpleSchema({
  name: {type: String},
  todos: {type: [Object]}
});
6 akan tersedia

Bagaimana cara memeriksa skema pengumpulan di MongoDB?

Periksa Skema MongoDB dengan Schema Explorer .
Klik kanan – Klik kanan pada koneksi apa pun di Pohon Koneksi dan pilih Analisis Skema
Tombol – Pilih koleksi dan klik Skema di toolbar global

Apakah ada skema di MongoDB?

MongoDB menggunakan model skema yang fleksibel , yang berarti bahwa dokumen dalam kumpulan tidak perlu memiliki bidang atau tipe data yang sama secara default. Setelah membuat skema aplikasi, Anda dapat menggunakan validasi skema untuk memastikan tidak ada perubahan skema yang tidak diinginkan atau tipe data yang tidak tepat.

Bagaimana cara melihat skema di Kompas MongoDB?

Klik nilai bagan. Dalam tampilan Skema, Anda bisa mengklik nilai bagan untuk menyusun kueri. .
Opsional. Pilih beberapa nilai. .
Opsional. Klik pada nilai bidang lain untuk membuat kueri gabungan. .
Opsional. Batalkan pilihan nilai. .
Jalankan kueri. Untuk menjalankan kueri, klik Analisis

Apa itu skema MongoDB?

Apa itu Skema? . Anda dapat menggunakan skema BSON Layanan Aplikasi Atlas, yang memperluas standar Skema JSON, untuk menentukan model data aplikasi Anda dan memvalidasi dokumen setiap kali dibuat, diubah, atau dihapus. a JSON object that defines the the structure and contents of your data. You can use Atlas App Services' BSON schemas, which extend the JSON Schema standard, to define your application's data model and validate documents whenever they're created, changed, or deleted.