2011-11-19 35 views
11

Hãy nói rằng tôi có một bộ sưu tập các tài liệu như:Làm cách nào để thực thi các khóa ngoại trong cơ sở dữ liệu NoSql (MongoDB)?

{ "_id" : 0 , "owner":0 "name":"Doc1"},{ "_id" : 1 , "owner":1, "name":"Doc1"}, etc 

Và, mặt khác chủ sở hữu được thể hiện dưới dạng một bộ sưu tập riêng biệt:

{ "_id" : 0 , "username":"John"}, { "_id" : 1 , "username":"Sam"} 

Làm thế nào tôi có thể chắc chắn rằng, khi Tôi chèn một tài liệu nó tham khảo người dùng một cách chính xác. Trong RDBMS trường cũ, điều này có thể dễ dàng được thực hiện bằng cách sử dụng khóa ngoại.

Tôi biết rằng tôi có thể kiểm tra tính chính xác của việc chèn từ mã doanh nghiệp của tôi, NHƯNG nếu một kẻ tấn công tampers với yêu cầu của tôi đến máy chủ và đặt "chủ sở hữu": 100, và Mongo không ném bất kỳ ngoại lệ trở lại.

Tôi muốn biết tình huống này nên được xử lý như thế nào trong một ứng dụng thực tế.

Cảm ơn bạn trước!

+1

Nếu kẻ tấn công có thể giả mạo yêu cầu của bạn, điều gì khiến bạn cho rằng họ không thể giả mạo ngoại lệ phản hồi? – deed02392

Trả lời

12

MongoDB không có khóa ngoài (như bạn có thể nhận thấy). Về cơ bản, câu trả lời là do đó, "Đừng để người dùng làm xáo trộn các yêu cầu. Chỉ cho phép ứng dụng chèn dữ liệu tuân theo các quy tắc toàn vẹn tham chiếu của bạn."

MongoDB là rất tốt trong nhiều cách ... nhưng nếu bạn thấy rằng bạn cần chìa khóa nước ngoài, sau đó nó có lẽ không phải là giải pháp chính xác cho vấn đề của bạn.

13

Để trả lời câu hỏi cụ thể của bạn - trong khi MongoDB khuyến khích xử lý các mối quan hệ khóa ngoài ở phía máy khách, chúng cũng cung cấp ý tưởng "Tham khảo cơ sở dữ liệu" - Xem this help page.

Điều đó nói rằng, Tôi không khuyên bạn nên sử dụng DBRef. Hoặc để mã khách hàng của bạn quản lý các liên kết hoặc (tốt hơn) liên kết các tài liệu với nhau ngay từ đầu. Bạn có thể muốn xem xét nhúng "tài liệu" của chủ sở hữu vào bên trong đối tượng chủ sở hữu. Tập hợp các tài liệu của bạn để phù hợp với các mẫu sử dụng của bạn và MongoDB sẽ tỏa sáng.

+0

+1 cho một gợi ý về cách cơ cấu lại để tránh vấn đề này. – deed02392

0

Tôi cũng sẽ lưu ý rằng nếu tên người dùng là duy nhất, thì hãy sử dụng chúng làm _id. Bạn sẽ lưu vào một chỉ mục. Trong tài liệu được lưu trữ, đặt giá trị của 'chủ sở hữu' trong ứng dụng làm giá trị của 'tên người dùng' khi tài liệu được tạo và không bao giờ cho phép bất kỳ đoạn mã nào khác cập nhật nó.

Nếu có yêu cầu để thay đổi chủ sở hữu, sau đó cung cấp API appropirate với quy tắc kinh doanh được triển khai.

Không cần bất kỳ khóa ngoại nào.

+1

Ngoại trừ, nếu bạn làm điều này, nếu người dùng muốn thay đổi tên người dùng của mình, bạn phải xóa bản ghi hiện có và sau đó chèn một bản ghi mới bằng tên người dùng đã thay đổi. –

0

Nếu ai đó thực sự muốn thực thi khóa Ngoại trong Dự án/WebApp. Sau đó, bạn nên có cách tiếp cận MixSQL tức là SQL + NoSQL

Tôi muốn dữ liệu Bulky không có nhiều tham chiếu hơn thì có thể lưu trữ trong kho lưu trữ cơ sở dữ liệu NoSQL. Giống như: Khách sạn hoặc Địa điểm loại dữ liệu.

Nhưng nếu có một số điều nghiêm trọng như mô-đun OAuth Bảng, TokenStore và UserDetails và UserRole (Bảng ánh xạ), v.v ... thì bạn có thể đi với SQL.

0

Là giải pháp NoSQL, bạn có thể sử dụng MariaDB (NewSQL) Kết hợp SQL và NoSQL của nó và được các nhà phát triển MySQL triển khai với hiệu suất tuyệt vời.

0

Đây là mối quan hệ một đối một. Tốt hơn là nhúng một tài liệu vào một tài liệu khác, thay vì duy trì các bộ sưu tập riêng biệt. Kiểm tra here về cách mô hình hóa chúng trong Mongodb và lợi thế của chúng.

Mặc dù không được đề cập rõ ràng trong tài liệu, việc nhúng cho bạn hiệu ứng tương tự như ràng buộc khóa ngoại. Chỉ muốn làm cho ý tưởng này rõ ràng. Khi bạn có hai bộ sưu tập như thế:

C1:

{ "_id" : 0 , "owner":0 "name":"Doc1"},{ "_id" : 1 , "owner":1, "name":"Doc1"}, etc 

C2:

{ "_id" : 0 , "username":"John"}, { "_id" : 1 , "username":"Sam"} 

Và nếu bạn đã tuyên bố ràng buộc khoá ngoại trên C2._id để tham khảo C1._id (giả sử MongoDB cho phép nó) , điều đó có nghĩa là bạn không thể chèn tài liệu vào C2 trong đó C2._id không tồn tại trong C1. So sánh điều này với tài liệu được nhúng:

{ 
    "_id" : 0 , 
    "owner" : 0, 
    "name" : "Doc1", 
    "owner_details" : { 
     "username" : "John" 
    } 
} 

Trường owner_details đại diện cho dữ liệu từ bộ sưu tập C2 và các trường còn lại đại diện cho dữ liệu từ C1. Bạn không thể thêm trường owner_details vào tài liệu không tồn tại. Về cơ bản bạn đang đạt được hiệu quả tương tự.

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