Câu hỏi hay, tôi cũng đang xem xét điều này.
Tạo một phiên bản mới trên mỗi thay đổi
Tôi đã xem qua mô-đun Phiên bản của trình điều khiển Mongoid cho Ruby. Tôi đã không sử dụng nó cho mình, nhưng từ những gì tôi có thể tìm thấy , nó thêm một số phiên bản cho mỗi tài liệu. Các phiên bản cũ hơn được nhúng trong chính tài liệu. Hạn chế lớn là toàn bộ tài liệu được sao chép trên mỗi thay đổi , điều này sẽ dẫn đến rất nhiều nội dung trùng lặp được lưu trữ khi bạn xử lý các tài liệu lớn. Cách tiếp cận này là tốt mặc dù khi bạn xử lý các tài liệu có kích thước nhỏ và / hoặc không thường xuyên cập nhật tài liệu.
Chỉ lưu trữ các thay đổi trong phiên bản mới
Một cách tiếp cận khác là chỉ lưu trữ các trường đã thay đổi trong phiên bản mới . Sau đó, bạn có thể 'làm phẳng' lịch sử của mình để xây dựng lại bất kỳ phiên bản nào của tài liệu. Mặc dù điều này khá phức tạp, vì bạn cần theo dõi các thay đổi trong mô hình của mình và lưu trữ các bản cập nhật và xóa theo cách mà ứng dụng của bạn có thể xây dựng lại tài liệu cập nhật. Điều này có thể khó khăn, vì bạn đang xử lý các tài liệu có cấu trúc chứ không phải các bảng SQL phẳng.
Lưu trữ các thay đổi trong tài liệu
Mỗi lĩnh vực cũng có thể có một lịch sử cá nhân. Tái cấu trúc tài liệu cho một phiên bản nhất định theo cách này dễ dàng hơn nhiều. Trong ứng dụng của bạn, bạn không phải theo dõi rõ ràng các thay đổi, mà chỉ cần tạo một phiên bản mới của tài sản khi bạn thay đổi giá trị của nó. Một tài liệu có thể trông giống như thế này:
{
_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" }
]
}
]
}
Việc đánh dấu một phần tài liệu là đã bị xóa trong một phiên bản vẫn còn hơi khó xử. Bạn có thể giới thiệu một state
trường cho các phần có thể bị xóa / khôi phục khỏi ứng dụng của bạn:
{
author: "xxx",
body: [
{ version: 4, value: "Spam" }
],
state: [
{ version: 4, deleted: false },
{ version: 5, deleted: true }
]
}
Với mỗi cách tiếp cận này, bạn có thể lưu trữ một phiên bản cập nhật và làm phẳng trong một bộ sưu tập và dữ liệu lịch sử trong một bộ sưu tập riêng biệt. Điều này sẽ cải thiện thời gian truy vấn nếu bạn chỉ quan tâm đến phiên bản mới nhất của tài liệu. Nhưng khi bạn cần cả phiên bản mới nhất và dữ liệu lịch sử, bạn sẽ cần thực hiện hai truy vấn, thay vì một truy vấn. Vì vậy, việc lựa chọn sử dụng một bộ sưu tập duy nhất so với hai bộ sưu tập riêng biệt sẽ phụ thuộc vào tần suất ứng dụng của bạn cần các phiên bản lịch sử .
Hầu hết câu trả lời này chỉ là một suy nghĩ vẩn vơ trong suy nghĩ của tôi, tôi chưa thực sự thử bất kỳ câu hỏi nào trong số này. Nhìn lại nó, tùy chọn đầu tiên có lẽ là giải pháp dễ nhất và tốt nhất, trừ khi chi phí chung của dữ liệu trùng lặp rất có ý nghĩa đối với ứng dụng của bạn. Tùy chọn thứ hai khá phức tạp và có lẽ không đáng để bỏ công sức. Tùy chọn thứ ba về cơ bản là tối ưu hóa tùy chọn hai và sẽ dễ thực hiện hơn, nhưng có lẽ không đáng để nỗ lực thực hiện trừ khi bạn thực sự không thể đi với tùy chọn thứ nhất.
Mong được phản hồi về vấn đề này và những giải pháp của người khác cho vấn đề này :)