Pertanyaan bagus, saya juga melihat ke dalam ini.
Buat versi baru pada setiap perubahan
Saya menemukan modul Versioning dari driver Mongoid untuk Ruby. Saya belum menggunakannya sendiri, tetapi dari apa yang saya temukan , itu menambahkan nomor versi ke setiap dokumen. Versi yang lebih lama tertanam dalam dokumen itu sendiri. Kelemahan utama adalah bahwa seluruh dokumen digandakan pada setiap perubahan , yang akan menghasilkan banyak konten duplikat disimpan ketika Anda berurusan dengan dokumen besar. Pendekatan ini baik-baik saja meskipun ketika Anda berurusan dengan dokumen berukuran kecil dan / atau tidak terlalu sering memperbarui dokumen.
Hanya simpan perubahan dalam versi baru
Pendekatan lain adalah dengan menyimpan hanya bidang yang diubah dalam versi baru . Kemudian Anda dapat 'meratakan' riwayat Anda untuk merekonstruksi versi dokumen apa pun. Ini agak rumit, karena Anda perlu melacak perubahan dalam model Anda dan menyimpan pembaruan dan menghapus dengan cara aplikasi Anda dapat merekonstruksi dokumen terbaru. Ini mungkin rumit, karena Anda berurusan dengan dokumen terstruktur daripada tabel SQL datar.
Simpan perubahan di dalam dokumen
Setiap bidang juga dapat memiliki riwayat individu. Rekonstruksi dokumen ke versi yang diberikan jauh lebih mudah dengan cara ini. Di aplikasi Anda, Anda tidak perlu melacak perubahan secara eksplisit, tetapi cukup buat versi baru dari properti saat Anda mengubah nilainya. Sebuah dokumen dapat terlihat seperti ini:
{
_id: "4c6b9456f61f000000007ba6"
title: [
{ version: 1, value: "Hello world" },
{ version: 6, value: "Foo" }
],
body: [
{ version: 1, value: "Is this thing on?" },
{ version: 2, value: "What should I write?" },
{ version: 6, value: "This is the new body" }
],
tags: [
{ version: 1, value: [ "test", "trivial" ] },
{ version: 6, value: [ "foo", "test" ] }
],
comments: [
{
author: "joe", // Unversioned field
body: [
{ version: 3, value: "Something cool" }
]
},
{
author: "xxx",
body: [
{ version: 4, value: "Spam" },
{ version: 5, deleted: true }
]
},
{
author: "jim",
body: [
{ version: 7, value: "Not bad" },
{ version: 8, value: "Not bad at all" }
]
}
]
}
Menandai bagian dari dokumen sebagai dihapus dalam versi masih agak canggung. Anda bisa memperkenalkan state
bidang untuk bagian-bagian yang dapat dihapus / dipulihkan dari aplikasi Anda:
{
author: "xxx",
body: [
{ version: 4, value: "Spam" }
],
state: [
{ version: 4, deleted: false },
{ version: 5, deleted: true }
]
}
Dengan masing-masing pendekatan ini, Anda dapat menyimpan versi terbaru dan rata dalam satu koleksi dan data riwayat dalam koleksi terpisah. Ini akan meningkatkan waktu kueri jika Anda hanya tertarik pada versi terbaru dokumen. Tetapi ketika Anda membutuhkan versi terbaru dan data historis, Anda harus melakukan dua pertanyaan, bukan satu. Jadi pilihan untuk menggunakan satu koleksi vs. dua koleksi terpisah harus bergantung pada seberapa sering aplikasi Anda membutuhkan versi historis .
Sebagian besar dari jawaban ini hanyalah tumpukan pikiran saya, saya belum benar-benar mencoba semua ini. Melihat ke belakang, opsi pertama mungkin adalah solusi termudah dan terbaik, kecuali jika overhead data duplikat sangat signifikan untuk aplikasi Anda. Pilihan kedua cukup kompleks dan mungkin tidak sepadan dengan usaha. Opsi ketiga pada dasarnya adalah optimalisasi opsi dua dan harus lebih mudah diimplementasikan, tetapi mungkin tidak sepadan dengan upaya implementasi kecuali Anda benar-benar tidak bisa menggunakan opsi satu.
Menantikan umpan balik tentang ini, dan solusi orang lain untuk masalah ini :)