2014-07-02 18 views
5

Vì vậy, tôi có một ứng dụng mà cần phải lưu trữ thông tin cấu hình nhất định, và vì vậy tôi đang lên kế hoạch về lưu trữ các configs như tài liệu JSON đơn giản trong Mongo:Đối tượng được phiên bản/Ánh xạ JSON đến/từ Mongo?

appConfig: { 
    fizz: true, 
    buzz: 34 
} 

này có thể ánh xạ một Java POJO/tổ chức như:

public class AppConfig { 
    private boolean fizz; 
    private int buzz; 
} 

vv Thông thường, với cơ sở dữ liệu quan hệ, tôi sử dụng Hibernate/JPA cho O/R ánh xạ từ dữ liệu bảng đến/từ thực thể Java. Tôi tin đồng hành JSON/Mongo gần nhất với bảng/Hibernate là một kết hợp Morphia/GSON: sử dụng Morphia để kết nối từ ứng dụng Java của tôi tới Mongo và sau đó sử dụng GSON để O/J ánh xạ JSON tới/từ Java POJOs/thực thể.

Vấn đề ở đây là, theo thời gian, cấu trúc tài liệu appConfig của tôi sẽ thay đổi. Nó có thể là một cái gì đó đơn giản như:

appConfig: { 
    fizz: true, 
    buzz: 34 
    foo: "Hello!" 
} 

Mà sau đó sẽ yêu cầu các POJO/tổ chức để trở thành:

public class AppConfig { 
    private boolean fizz; 
    private int buzz; 
    private String foo; 
} 

Nhưng vấn đề là tôi có thể có hàng chục ngàn tài liệu JSON đã được lưu trữ trong Mongo không có foo thuộc tính trong đó. Trong trường hợp cụ thể này, giải pháp rõ ràng là để thiết lập một mặc định trên tài sản như:

public class AppConfig { 
    private boolean fizz; 
    private int buzz; 
    private String foo = "Hello!" 
} 

Tuy nhiên trong thực tế, cuối cùng các AppConfig tài liệu/schema/cấu trúc có thể thay đổi nhiều đến nỗi nó không có cách nào, hình dạng hoặc hình thức tương tự như thiết kế ban đầu của nó. Nhưng kicker là: Tôi cần phải tương thích ngược và tốt nhất là có khả năng cập nhật/chuyển đổi tài liệu để phù hợp với lược đồ/cấu trúc mới khi thích hợp.

Câu hỏi của tôi: vấn đề "phiên bản tài liệu" này thường được giải quyết như thế nào?

Trả lời

1

Tôi đoán bên dưới chủ đề sẽ giúp bạn mặc dù nó không phải là về versioning tài liệu trong DB, và nó đã được thực hiện bằng lò xo dữ liệu MongoDB,

How to add a final field to an existing spring-data-mongodb document collection?

Vì vậy, bạn có thể gán giá trị cho POJO dựa trên sự tồn tại của thuộc tính trong tài liệu bằng cách sử dụng việc thực hiện Chuyển đổi.

+0

Cảm ơn @Lucky Coder (+1), nhưng điều đó có vẻ là thêm về lĩnh vực thức hơn xử lý thay đổi phiên bản tài liệu giản đồ kết hợp với JPA. – IAmYourFaja

1

Bạn có một vài lựa chọn với thuốc phiện, ít nhất. Bạn có thể sử dụng tên lớp được phiên bản, sau đó dựa vào việc sử dụng thuộc tính className của morphia để tìm phiên bản lớp đúng. Sau đó, ứng dụng của bạn sẽ phải di chuyển đối tượng cũ đó sang định nghĩa lớp mới. Một tùy chọn khác là sử dụng @PreLoad và xoa bóp DBObject sắp ra khỏi mongo với hình dạng mới trước khi morphia ánh xạ DBObject đến lớp học của bạn. Sử dụng trường phiên bản trên lớp, bạn có thể xác định việc di chuyển nào sẽ chạy khi dữ liệu được tải. Từ thời điểm đó, nó sẽ trông giống như hình thức mới để làm mờ và sẽ lập bản đồ liền mạch. Khi bạn lưu đối tượng cấu hình đó trở lại mongo, nó sẽ ở dạng mới và tải tiếp theo sẽ không cần phải chạy di chuyển.

5

Tôi thường giải quyết vấn đề này bằng cách thêm trường phiên bản vào từng tài liệu trong bộ sưu tập.

Bạn có thể có một số tài liệu trong bộ sưu tập AppConfig:

{ 
    _id: 1, 
    fizz: true, 
    buzz: 34 
} 

{ 
    _id: 2, 
    version: 1, 
    fizz: false, 
    buzz: 36, 
    foo: "Hello!" 
} 

{ 
    _id: 3, 
    version: 1, 
    fizz: true, 
    buzz: 42, 
    foo: "Goodbye" 
} 

Trong ví dụ trên, có hai văn bản tại phiên bản một, và một tài liệu cũ tại phiên bản zero (trong mô hình này, tôi thường giải thích một trường phiên bản thiếu hoặc không có phiên bản là 0, vì tôi luôn chỉ thêm trường này khi tôi đang phiên bản bằng tài liệu trong sản xuất).

Hai nguyên tắc của mô hình này:

  1. Tài liệu luôn luôn được lưu tại phiên bản mới nhất khi họ đang thực sự thay đổi.
  2. Khi tài liệu được đọc, nếu tài liệu không có ở phiên bản mới nhất, nó sẽ được nâng cấp rõ ràng lên phiên bản mới nhất.

Bạn làm điều này bằng cách kiểm tra các lĩnh vực phiên bản, và thực hiện một sự chuyển đổi khi phiên bản không phải là đủ mới:

DBObject update(DBObject document) { 
    if (document.getInt("version", 0) < 1) { 
     document.put("foo", "Hello!"); //add default value for foo 
     document.put("version", 1); 
    } 
    return document; 
} 

di cư này có thể khá dễ dàng thêm các trường với các giá trị mặc định, đổi tên các lĩnh vực, và loại bỏ các trường. Vì nó nằm trong mã ứng dụng, bạn có thể thực hiện các phép tính phức tạp hơn khi cần thiết.

Khi tài liệu đã được di chuyển, bạn có thể chạy nó qua bất kỳ giải pháp ODM nào bạn muốn chuyển đổi nó thành các đối tượng Java. Giải pháp này không còn phải lo lắng về phiên bản, vì các tài liệu mà nó đề cập đến là tất cả hiện tại!

Với Morphia, điều này có thể được thực hiện bằng cách sử dụng chú thích @PreLoad.

Hai hãy cẩn thận:

  1. Đôi khi bạn có thể muốn lưu các tài liệu nâng cấp lại cơ sở dữ liệu ngay lập tức. Lý do phổ biến nhất cho điều này là khi di chuyển là tốn kém, việc di chuyển không xác định hoặc tích hợp với cơ sở dữ liệu khác hoặc bạn đang vội vàng nâng cấp phiên bản cũ.

  2. Thêm hoặc đổi tên các trường được sử dụng làm tiêu chí trong truy vấn sẽ phức tạp hơn một chút. Trong thực tế, bạn có thể cần thực hiện nhiều truy vấn và thống nhất kết quả.

Theo tôi, mô hình này nhấn mạnh một trong những lợi thế lớn của MongoDB: kể từ khi tài liệu được phiên bản trong ứng dụng, bạn liên tục có thể di chuyển dữ liệu cơ quan đại diện trong ứng dụng mà không cần bất kỳ ẩn "giai đoạn di cư" như bạn sẽ cần với một cơ sở dữ liệu SQL.

2

Các JSON deserialzer giải quyết này một cách rất đơn giản để bạn, (sử dụng JAVA)

Chỉ cần cho phép POJO của bạn/tổ chức để phát triển với các lĩnh vực mới. Khi bạn deserialize JSON của bạn từ mongo cho bạn thực thể - tất cả các trường bị thiếu sẽ là null.

mongoDocument v1 :  Entity of v3 
    { 
     fizz="abc",  -->  fizz  = "abc"; 
     buzz=123   -->  buzz  = 123; 
         -->  newObj = null; 
         -->  obj_v3 = null; 

    } 

Bạn thậm chí có thể sử dụng cách khác xung quanh nếu bạn muốn có bạn máy chủ cũ làm việc với các đối tượng cơ sở dữ liệu mới:

mongoDocument v3  :  Entity of v1 
    { 
     fizz:"abc",  -->  fizz  = "abc"; 
     buzz:123,   -->  buzz  = 123; 
     newObj:"zzz",  -->  
     obj_v3:"b   -->  

    } 

Tùy nếu họ có các lĩnh vực hay không - nó sẽ được dân cư bởi deserializer. Hãy nhớ rằng các boolean không phù hợp nhất cho điều này vì chúng có thể mặc định là false (tùy thuộc vào deserializer bạn sử dụng).

Vì vậy, trừ khi bạn đang tích cực sẽ làm việc với phiên bản của các đối tượng của bạn tại sao bận tâm với overhead khi bạn có thể xây dựng một di sản an toàn thực máy chủ gì chỉ với một vài kiểm tra null có thể xử lý bất kỳ của các đối tượng cũ.

Tôi hy vọng đề xuất này có thể giúp bạn với thiết lập của bạn

Các vấn đề liên quan