Mengapa Mongoose memiliki skema dan model?

94

Kedua jenis objek tersebut tampak begitu dekat satu sama lain sehingga memiliki keduanya terasa mubazir. Apa gunanya memiliki kedua skema dan model?

Randomblue
sumber

Jawaban:

61

Seringkali cara termudah untuk menjawab jenis pertanyaan ini adalah dengan sebuah contoh. Dalam hal ini, seseorang telah melakukannya untuk saya :)

Lihat di sini:

http://rawberg.com/blog/nodejs/mongoose-orm-nested-models/

EDIT: Posting asli (seperti yang disebutkan di komentar) sepertinya sudah tidak ada lagi, jadi saya mereproduksinya di bawah ini. Jika ia pernah kembali, atau baru saja pindah, beri tahu saya.

Ini memberikan deskripsi yang layak tentang penggunaan skema dalam model di luwak dan mengapa Anda ingin melakukannya, dan juga menunjukkan kepada Anda cara mendorong tugas melalui model sementara skema adalah tentang struktur, dll.

Posting Asli:

Mari kita mulai dengan contoh sederhana menyematkan skema di dalam model.

var TaskSchema = new Schema({
    name: String,
    priority: Number
});

TaskSchema.virtual('nameandpriority')
    .get( function () {
        return this.name + '(' + this.priority + ')';
    });

TaskSchema.method('isHighPriority', function() {
    if(this.priority === 1) {
        return true;
    } else {
        return false;
    }
}); 

var ListSchema = new Schema({
    name: String,
    tasks: [TaskSchema]
});

mongoose.model('List', ListSchema);

var List = mongoose.model('List');

var sampleList = new List({name:'Sample List'});

Saya membuat TaskSchemaobjek baru dengan info dasar yang mungkin dimiliki tugas. Atribut virtual Mongoose disiapkan untuk menggabungkan nama dan prioritas Tugas dengan mudah. Saya hanya menentukan pengambil di sini tetapi penyetel virtual juga didukung.

Saya juga mendefinisikan metode tugas sederhana yang dipanggil isHighPriorityuntuk mendemonstrasikan bagaimana metode bekerja dengan pengaturan ini.

Dalam ListSchemadefinisi Anda akan melihat bagaimana kunci tugas dikonfigurasi untuk menampung array TaskSchemaobjek. Kunci tugas akan menjadi sebuah instance DocumentArrayyang menyediakan metode khusus untuk menangani dokumen Mongo yang disematkan.

Untuk saat ini saya hanya meneruskan ListSchemaobjek ke mongoose.model dan meninggalkan TaskSchema. Secara teknis tidak perlu TaskSchemadijadikan model formal karena kita tidak akan menyimpannya dalam koleksi sendiri. Nanti saya akan menunjukkan kepada Anda bagaimana itu tidak merugikan apa pun jika Anda melakukannya dan itu dapat membantu mengatur semua model Anda dengan cara yang sama terutama ketika mereka mulai mencakup banyak file.

Dengan Listpengaturan model, mari tambahkan beberapa tugas ke dalamnya dan simpan ke Mongo.

var List = mongoose.model('List');
var sampleList = new List({name:'Sample List'});

sampleList.tasks.push(
    {name:'task one', priority:1}, 
    {name:'task two', priority:5}
);

sampleList.save(function(err) {
    if (err) {
        console.log('error adding new list');
        console.log(err);
    } else {
        console.log('new list successfully saved'); 
    }
});

Atribut tugas pada instance Listmodel kita ( simpleList) berfungsi seperti array JavaScript biasa dan kita dapat menambahkan tugas baru ke dalamnya menggunakan push. Hal penting yang perlu diperhatikan adalah tugas ditambahkan sebagai objek JavaScript biasa. Ini adalah perbedaan halus yang mungkin tidak langsung intuitif.

Anda dapat memverifikasi dari shell Mongo bahwa daftar dan tugas baru disimpan ke mongo.

db.lists.find()
{ "tasks" : [
    {
        "_id" : ObjectId("4dd1cbeed77909f507000002"),
        "priority" : 1,
        "name" : "task one"
    },
    {
        "_id" : ObjectId("4dd1cbeed77909f507000003"),
        "priority" : 5,
        "name" : "task two"
    }
], "_id" : ObjectId("4dd1cbeed77909f507000001"), "name" : "Sample List" }

Sekarang kita dapat menggunakan ObjectIduntuk menarik Sample Listdan mengulangi tugas-tugasnya.

List.findById('4dd1cbeed77909f507000001', function(err, list) {
    console.log(list.name + ' retrieved');
    list.tasks.forEach(function(task, index, array) {
        console.log(task.name);
        console.log(task.nameandpriority);
        console.log(task.isHighPriority());
    });
});

Jika Anda menjalankan sedikit kode terakhir, Anda akan mendapatkan pesan kesalahan yang mengatakan bahwa dokumen yang disematkan tidak memiliki metode isHighPriority. Dalam versi Mongoose saat ini, Anda tidak dapat mengakses metode pada skema tersemat secara langsung. Ada tiket terbuka untuk memperbaikinya dan setelah mengajukan pertanyaan ke Grup Google Mongoose, manimal45 memposting solusi yang berguna untuk digunakan saat ini.

List.findById('4dd1cbeed77909f507000001', function(err, list) {
    console.log(list.name + ' retrieved');
    list.tasks.forEach(function(task, index, array) {
        console.log(task.name);
        console.log(task.nameandpriority);
        console.log(task._schema.methods.isHighPriority.apply(task));
    });
});

Jika Anda menjalankan kode itu, Anda akan melihat keluaran berikut pada baris perintah.

Sample List retrieved
task one
task one (1)
true
task two
task two (5)
false

Dengan pemikiran tersebut, mari kita TaskSchemaubah menjadi model Mongoose.

mongoose.model('Task', TaskSchema);

var Task = mongoose.model('Task');

var ListSchema = new Schema({
    name: String,
    tasks: [Task.schema]
});

mongoose.model('List', ListSchema);

var List = mongoose.model('List');

The TaskSchemadefinisi adalah sama seperti sebelumnya jadi aku meninggalkannya keluar. Setelah berubah menjadi model, kita masih dapat mengakses objek Skema yang mendasarinya menggunakan notasi titik.

Mari buat daftar baru dan sematkan dua contoh model Tugas di dalamnya.

var demoList = new List({name:'Demo List'});

var taskThree = new Task({name:'task three', priority:10});
var taskFour = new Task({name:'task four', priority:11});

demoList.tasks.push(taskThree.toObject(), taskFour.toObject());

demoList.save(function(err) {
    if (err) {
        console.log('error adding new list');
        console.log(err);
    } else {
        console.log('new list successfully saved'); 
    }
});

Saat kami menyematkan contoh model Tugas ke dalam Daftar, kami meminta toObjectmereka untuk mengubah datanya menjadi objek JavaScript biasa yang List.tasks DocumentArraydiharapkan. Saat Anda menyimpan contoh model dengan cara ini dokumen Anda yang disematkan akan berisi ObjectIds.

Contoh kode lengkap tersedia sebagai intinya . Semoga solusi ini membantu memuluskan semuanya seiring Mongoose terus berkembang. Saya masih cukup baru mengenal Mongoose dan MongoDB jadi jangan ragu untuk membagikan solusi dan tip yang lebih baik di komentar. Selamat pemodelan data!

Adam Comerford
sumber
3
Umumnya disarankan untuk tidak mengirimkan tautan kosong sebagai jawaban atas pertanyaan yang diposting di SO karena tautan tersebut mungkin berhenti berfungsi (seperti dalam kasus ini). Setidaknya salin / tempel dan kutip bagian relevan dari artikel yang Anda tautkan.
Behrang Saeedzadeh
1
selesai - itu masih dalam cache Google, jadi relatif sederhana
Adam Comerford
1
Sebagai catatan, masalah metode dokumen tersemat telah diperbaiki: github.com/LearnBoost/mongoose/issues/249#ref-commit-e18077a
Dakota
5
Saya tidak mencoba menghujani parade siapa pun, tetapi jawaban ini lebih seperti tutorial: menjawab bagaimana, tetapi bukan mengapa. Meskipun memiliki lebih sedikit suara, saya menemukan jawaban berikut jauh lebih membantu: stackoverflow.com/a/22950402/26331
aaaidan
2
Saya telah melihat jawaban itu (dan memberi suara positif), yang ini dijawab dan diterima lebih dari 2 tahun sebelumnya. Saya senang ada jawaban yang lebih baik untuk ditemukan, tidak ada hujan di parade siapa pun dan telah ada tautan ke jawaban yang Anda rujuk dalam komentar pertanyaan sejak Feb 2015 jadi saya tidak merasa perlu menautkannya sendiri
Adam Comerford
54

Skema adalah objek yang menentukan struktur semua dokumen yang akan disimpan dalam koleksi MongoDB Anda; ini memungkinkan Anda untuk menentukan jenis dan validator untuk semua item data Anda.

Model adalah objek yang memberi Anda akses mudah ke koleksi bernama, memungkinkan Anda untuk menanyakan koleksi dan menggunakan Skema untuk memvalidasi dokumen apa pun yang Anda simpan ke koleksi itu. Itu dibuat dengan menggabungkan Skema, Koneksi, dan nama koleksi.

Aslinya diutarakan oleh Valeri Karpov, MongoDB Blog

Zeeshan Hassan Memon
sumber
5

Saya tidak berpikir jawaban yang diterima benar-benar menjawab pertanyaan yang diajukan. Jawabannya tidak menjelaskan mengapa Mongoose memutuskan untuk meminta developer menyediakan variabel Skema dan Model. Contoh kerangka kerja di mana mereka telah menghilangkan kebutuhan akan pengembanguntuk mendefinisikan skema data adalah django - pengembang menulis model mereka di file models.py, dan menyerahkannya ke kerangka kerja untuk mengelola skema. Alasan pertama yang terlintas dalam pikiran mengapa mereka melakukan ini, berdasarkan pengalaman saya dengan django, adalah kemudahan penggunaan. Mungkin yang lebih penting adalah prinsip KERING (jangan ulangi diri Anda sendiri) - Anda tidak perlu ingat untuk memperbarui skema saat Anda mengubah model - django akan melakukannya untuk Anda! Rails juga mengelola skema data untuk Anda - pengembang tidak mengedit skema secara langsung, tetapi mengubahnya dengan menentukan migrasi yang memanipulasi skema.

Salah satu alasan saya dapat memahami bahwa Mongoose akan memisahkan skema dan model adalah contoh di mana Anda ingin membangun model dari dua skema. Skenario seperti itu mungkin menimbulkan lebih banyak kerumitan daripada yang layak dikelola - jika Anda memiliki dua skema yang dikelola oleh satu model, mengapa mereka tidak menjadi satu skema?

Mungkin pertanyaan aslinya lebih merupakan peninggalan dari sistem database relasional tradisional. Di dunia NoSQL / Mongo, mungkin skema sedikit lebih fleksibel daripada MySQL / PostgreSQL, dan dengan demikian mengubah skema adalah praktik yang lebih umum.

johnklawlor.dll
sumber
Seolah skema vs. model tidak cukup Repeating Yourself, Anda mengalami lebih banyak duplikasi saat mencoba mempertahankan antarmuka TypeScript yang cocok , dan bahkan lebih banyak lagi saat membuat skema GraphQL.
Dan Dascalescu
0

Untuk memahami mengapa? Anda harus mengerti apa sebenarnya luwak?

Nah, luwak adalah pustaka pemodelan data objek untuk MongoDB dan Node JS, menyediakan tingkat abstraksi yang lebih tinggi. Jadi ini seperti hubungan antara Express dan Node, jadi Express adalah lapisan abstraksi di atas Node biasa, sedangkan Mongoose adalah lapisan abstraksi di atas driver MongoDB biasa.

Perpustakaan pemodelan data objek hanyalah cara bagi kita untuk menulis kode Javascript yang kemudian akan berinteraksi dengan database. Jadi kita bisa menggunakan driver MongoDB biasa untuk mengakses database kita, itu akan bekerja dengan baik.

Tetapi sebaliknya kami menggunakan Mongoose karena ini memberi kami lebih banyak fungsi di luar kotak, memungkinkan pengembangan aplikasi kami yang lebih cepat dan sederhana.

Jadi, beberapa fitur yang diberikan Mongoose kepada kita skema untuk memodelkan data dan hubungan kita, validasi data yang mudah, API kueri sederhana, middleware, dan banyak lagi.

Di Mongoose, skema adalah tempat kami memodelkan data kami, di mana kami menjelaskan struktur data, nilai default, dan validasi, lalu kami mengambil skema itu dan membuat model darinya, model pada dasarnya adalah pembungkus di sekitar skema, yang memungkinkan kita untuk benar-benar berinteraksi dengan database untuk membuat, menghapus, memperbarui, dan membaca dokumen.

masukkan deskripsi gambar di sini

Mari buat model dari skema.

const tourSchema = new mongoose.Schema({
  name: {
    type: String,
    required: [true, 'A tour must have a name'],
    unique: true,
  },
  rating: {
    type: Number,
    default: 4.5,
  },
  price: {
    type: Number,
    required: [true, 'A tour must have a price'],
  },
});
//tour model
const Tour = mongoose.model('Tour', tourSchema);

Menurut kesepakatan, huruf pertama nama model harus menggunakan huruf besar.

Mari buat contoh model kita yang kita buat menggunakan luwak dan skema. juga, berinteraksi dengan database kami.

const testTour = new Tour({ // instance of our model
  name: 'The Forest Hiker',
  rating: 4.7,
  price: 497,
});
 // saving testTour document into database
testTour
  .save()
  .then((doc) => {
    console.log(doc);
  })
  .catch((err) => {
    console.log(err);
  });

Jadi memiliki luwak schama dan modle membuat hidup kita lebih mudah.

Tuan
sumber