Khóa ngoại trong mongo?


96

nhập mô tả hình ảnh ở đây

Làm cách nào để thiết kế một lược đồ như vậy trong MongoDB? Tôi nghĩ rằng không có khóa ngoại!


9
Bạn đang suy nghĩ theo quan hệ, thay vì hướng về tài liệu. : P
Pat

6
Tại sao bạn lại sử dụng MongoDB nếu bạn muốn có một cơ sở dữ liệu quan hệ?
Adam Robinson

48
: D Tôi đang cố gắng hiểu phương pháp hướng tài liệu; Làm thế nào tôi có thể giải quyết nhiệm vụ này?
Mark Pegasov

Nếu bạn muốn câu trả lời cho cách suy nghĩ theo định hướng tài liệu, hãy xem stackoverflow.com/a/18637581/80428 . Câu trả lời được chấp nhận hiện tại hoạt động nhưng đang tạo cơ sở dữ liệu quan hệ cho một kho lưu trữ tài liệu, điều này không giống với NoSQL.
Jay Wick

Câu trả lời:


27

Bạn có thể quan tâm đến việc sử dụng ORM như Mongoid hoặc MongoMapper.

http://mongoid.org/docs/relations/referenced/1-n.html

Trong cơ sở dữ liệu NoSQL như MongoDB không có 'bảng' mà là tập hợp. Tài liệu được nhóm bên trong Bộ sưu tập. Bạn có thể có bất kỳ loại tài liệu nào - với bất kỳ loại dữ liệu nào - trong một bộ sưu tập duy nhất. Về cơ bản, trong cơ sở dữ liệu NoSQL, tùy thuộc vào bạn để quyết định cách tổ chức dữ liệu và các mối quan hệ của nó, nếu có.

Những gì Mongoid và MongoMapper làm là cung cấp cho bạn các phương pháp thuận tiện để thiết lập quan hệ khá dễ dàng. Kiểm tra liên kết tôi đã cung cấp cho bạn và hỏi bất kỳ điều gì.

Biên tập:

Trong mongoid, bạn sẽ viết lược đồ của mình như thế này:

class Student
  include Mongoid::Document

    field :name
    embeds_many :addresses
    embeds_many :scores    
end

class Address
  include Mongoid::Document

    field :address
    field :city
    field :state
    field :postalCode
    embedded_in :student
end

class Score
  include Mongoid::Document

    belongs_to :course
    field :grade, type: Float
    embedded_in :student
end


class Course
  include Mongoid::Document

  field :name
  has_many :scores  
end

Biên tập:

> db.foo.insert({group:"phones"})
> db.foo.find()                  
{ "_id" : ObjectId("4df6539ae90592692ccc9940"), "group" : "phones" }
{ "_id" : ObjectId("4df6540fe90592692ccc9941"), "group" : "phones" }
>db.foo.find({'_id':ObjectId("4df6539ae90592692ccc9940")}) 
{ "_id" : ObjectId("4df6539ae90592692ccc9940"), "group" : "phones" }

Bạn có thể sử dụng ObjectId đó để thực hiện quan hệ giữa các tài liệu.


Có tài liệu với các mục và tôi muốn liên kết các thành phố. Tôi đã tạo bộ sưu tập với các thành phố, nhưng tôi không biết cách liên kết các thành phố với các mục. PS xin lỗi vì tiếng anh kém của tôi.
Mark Pegasov

CẬP NHẬT. Tôi đang sử dụng PHP làm ngôn ngữ lập trình, làm thế nào tôi có thể sử dụng mongoid, nếu nó được viết bằng Ruby?
Mark Pegasov

1
@ Жирайр Казаросян: Ồ, tôi hiểu rồi :) Là một nhà phát triển Ruby khiến tôi chỉ nghĩ đến Ruby :) Tôi sợ rằng tôi không có kinh nghiệm với PHP và Mongo, nhưng bạn có thể kiểm tra liên kết này: mongodb.org/display/DOCS/ …
Nerian

1
@ Жирайр Казаросян: Tôi đã học Ruby on Rails với cuốn sách Phát triển web với Ruby on Rails của các lập trình viên thực dụng. Bạn cũng có thể nhận được phần giới thiệu miễn phí với video screencast này Codechool.com/courses/rails-for-zombies
Nerian

2
Đối với người đọc sau này, "bảng" là "bộ sưu tập" trong MongoDB. Hàng là Tài liệu, và Cột là Trường ... Đề phòng trường hợp bạn bị lẫn lộn.
cpu_meltdown

65

Làm thế nào để thiết kế bảng như thế này trong mongodb?

Đầu tiên, để làm rõ một số quy ước đặt tên. MongoDB sử dụng collectionsthay vì tables.

Tôi nghĩ rằng không có khóa ngoại!

Lấy mô hình sau:

student
{ 
  _id: ObjectId(...),
  name: 'Jane',
  courses: [
    { course: 'bio101', mark: 85 },
    { course: 'chem101', mark: 89 }
  ]
}

course
{
  _id: 'bio101',
  name: 'Biology 101',
  description: 'Introduction to biology'
}

Rõ ràng danh sách khóa học của Jane chỉ ra một số khóa học cụ thể. Cơ sở dữ liệu không áp dụng bất kỳ ràng buộc nào đối với hệ thống ( ví dụ: ràng buộc khóa ngoại ), do đó không có "xóa theo tầng" hoặc "cập nhật theo tầng". Tuy nhiên, cơ sở dữ liệu không chứa thông tin chính xác.

Ngoài ra, MongoDB có một tiêu chuẩn DBRef giúp chuẩn hóa việc tạo các tham chiếu này. Trên thực tế, nếu bạn nhìn vào liên kết đó, nó có một ví dụ tương tự.

Tôi có thể giải quyết công việc này như thế nào?

Để rõ ràng, MongoDB không phải là quan hệ. Không có tiêu chuẩn "hình thức bình thường". Bạn nên lập mô hình cơ sở dữ liệu của mình phù hợp với dữ liệu bạn lưu trữ và các truy vấn bạn định chạy.


2
Được rồi, nhưng làm cách nào để lấy dữ liệu tên tòa án từ bộ sưu tập học sinh? db.student.find () sẽ trả về một cái gì đó giống như các khóa học: [{course: 'bio101', mark: 85}]
Mark Pegasov

@ Жирайр Казаросян:> db.foo.find ({'_ id': ObjectId ("4df6539ae90592692ccc9940")}) -------------> {"_id": ObjectId ("4df6539ae90592692ccc9940"), "group": "phone"}
Nerian

Từ tài liệu mongo về DBREF: "Trừ khi bạn có lý do thuyết phục để sử dụng DBRefs, thay vào đó hãy sử dụng các tham chiếu thủ công."
kroiz

23

Chúng ta có thể định nghĩa cái gọi là foreign keytrong MongoDB. Tuy nhiên, chúng ta cần duy trì tính toàn vẹn của dữ liệu BẰNG CÁCH CỦA CHÚNG TÔI . Ví dụ,

student
{ 
  _id: ObjectId(...),
  name: 'Jane',
  courses: ['bio101', 'bio102']   // <= ids of the courses
}

course
{
  _id: 'bio101',
  name: 'Biology 101',
  description: 'Introduction to biology'
}

Các coursestrường chứa _ids của khóa học. Thật dễ dàng để xác định mối quan hệ một-nhiều. Tuy nhiên, nếu chúng ta muốn lấy tên khóa học của sinh viên Jane, chúng ta cần thực hiện một thao tác khác để lấy coursetài liệu qua _id.

Nếu khóa học bio101bị xóa, chúng ta cần thực hiện một thao tác khác để cập nhật coursestrường trong studenttài liệu.

Thêm: Thiết kế lược đồ MongoDB

Bản chất kiểu tài liệu của MongoDB hỗ trợ các cách linh hoạt để xác định mối quan hệ. Để xác định mối quan hệ một-nhiều:

Tài liệu được nhúng

  1. Thích hợp cho một-vài.
  2. Ưu điểm: không cần thực hiện thêm các truy vấn đối với tài liệu khác.
  3. Nhược điểm: không thể quản lý thực thể của các tài liệu nhúng riêng lẻ.

Thí dụ:

student
{
  name: 'Kate Monster',
  addresses : [
     { street: '123 Sesame St', city: 'Anytown', cc: 'USA' },
     { street: '123 Avenue Q', city: 'New York', cc: 'USA' }
  ]
}

Tham khảo trẻ em

Giống như ví dụ student/ courseở trên.

Tham khảo phụ huynh

Thích hợp cho một-đến-squillions, chẳng hạn như thông điệp nhật ký.

host
{
    _id : ObjectID('AAAB'),
    name : 'goofy.example.com',
    ipaddr : '127.66.66.66'
}

logmsg
{
    time : ISODate("2014-03-28T09:42:41.382Z"),
    message : 'cpu is on fire!',
    host: ObjectID('AAAB')       // Reference to the Host document
}

Hầu như, a hostlà cha mẹ của a logmsg. Tham chiếu đến hostid tiết kiệm nhiều không gian cho rằng các thông điệp nhật ký là squillions.

Người giới thiệu:

  1. 6 Quy tắc ngón tay cái cho thiết kế lược đồ MongoDB: Phần 1
  2. 6 Quy tắc ngón tay cái cho thiết kế lược đồ MongoDB: Phần 2
  3. 6 Quy tắc ngón tay cái cho thiết kế lược đồ MongoDB: Phần 3
  4. Mô hình mối quan hệ một-nhiều với tham chiếu tài liệu

19

Từ Sách MongoDB Nhỏ

Tuy nhiên, một giải pháp thay thế khác cho việc sử dụng các phép nối là không chuẩn hóa dữ liệu của bạn. Trước đây, quá trình không chuẩn hóa được dành riêng cho mã nhạy cảm với hiệu suất hoặc khi dữ liệu nên được chụp nhanh (như trong nhật ký kiểm tra). Tuy nhiên, với sự phổ biến ngày càng tăng của NoSQL, nhiều trong số đó không có liên kết, việc không chuẩn hóa như một phần của mô hình thông thường ngày càng trở nên phổ biến. Điều này không có nghĩa là bạn nên sao chép mọi thông tin trong mọi tài liệu. Tuy nhiên, thay vì để nỗi sợ hãi về dữ liệu trùng lặp thúc đẩy các quyết định thiết kế của bạn, hãy xem xét việc lập mô hình dữ liệu của bạn dựa trên thông tin thuộc về tài liệu nào.

Vì thế,

student
{ 
    _id: ObjectId(...),
    name: 'Jane',
    courses: [
    { 
        name: 'Biology 101', 
        mark: 85, 
        id:bio101 
    },
  ]
}

Nếu nó là dữ liệu RESTful API, hãy thay thế id khóa học bằng liên kết GET tới tài nguyên khóa học


Tôi nghĩ đây là câu trả lời chính xác. Trừ khi bạn đang lưu trữ dữ liệu quan hệ trong mongo, trong trường hợp đó, bạn thực sự nên đặt câu hỏi tại sao bạn lại sử dụng mongo.
Jay Wick

0

Mục đích của ForeignKey là ngăn việc tạo dữ liệu nếu giá trị trường không khớp với ForeignKey của nó. Để thực hiện điều này trong MongoDB, chúng tôi sử dụng phần mềm trung gian Schema để đảm bảo tính nhất quán của dữ liệu.

Vui lòng xem tài liệu. https://mongoosejs.com/docs/middleware.html#pre

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.