Kunci asing di mongo?


98

masukkan deskripsi gambar di sini

Bagaimana cara mendesain skema seperti ini di MongoDB? Saya pikir tidak ada kunci asing!


10
Anda berpikir secara relasional, bukan berorientasi dokumen. : P
Tepuk

6
Mengapa Anda menggunakan MongoDB jika Anda menginginkan database relasional?
Adam Robinson

49
: D Saya mencoba memahami metode berorientasi dokumen; Bagaimana saya bisa menyelesaikan tugas ini?
Mark Pegasov

Jika Anda menginginkan jawaban untuk cara berpikir yang berorientasi pada dokumen, lihat stackoverflow.com/a/18637581/80428 . Jawaban yang diterima saat ini berfungsi tetapi menggunakan database relasional ke penyimpanan dokumen yang bukan tentang NoSQL.
Jay Wick

Jawaban:


27

Anda mungkin tertarik menggunakan ORM seperti Mongoid atau MongoMapper.

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

Dalam database NoSQL seperti MongoDB tidak ada 'tabel' tetapi koleksi. Dokumen dikelompokkan di dalam Koleksi. Anda dapat memiliki jenis dokumen apa pun - dengan jenis data apa pun - dalam satu koleksi. Pada dasarnya, dalam database NoSQL, terserah Anda untuk memutuskan bagaimana mengatur data dan hubungannya, jika ada.

Apa yang dilakukan Mongoid dan MongoMapper adalah memberi Anda metode yang nyaman untuk mengatur hubungan dengan mudah. Lihat tautan yang saya berikan kepada Anda dan tanyakan apa saja.

Edit:

Di mongoid Anda akan menulis skema Anda seperti ini:

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

Edit:

> 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" }

Anda dapat menggunakan ObjectId itu untuk melakukan hubungan antar dokumen.


Ada dokumen dengan item, dan saya ingin mengikat kota. Saya telah membuat koleksi dengan kota, tetapi saya tidak tahu cara mengikat kota dengan item. PS maaf untuk bahasa Inggris saya yang buruk.
Mark Pegasov

UPD. Saya menggunakan PHP sebagai bahasa pemrograman, bagaimana cara menggunakan mongoid, jika ditulis dengan Ruby?
Mark Pegasov

1
@ Жирайр Казаросян: Oh begitu :) Menjadi pengembang Ruby membuat saya hanya berpikir di Ruby :) Saya khawatir saya tidak memiliki pengalaman dengan PHP dan Mongo, tetapi Anda dapat memeriksa tautan ini: mongodb.org/display/DOCS/ …
Nerian

1
@ Жирайр Казаросян: Saya mempelajari Ruby on Rails dengan buku Pengembangan web dengan Ruby on Rails, oleh programmer pragmatis. Anda juga bisa mendapatkan pengantar secara gratis dengan screencast codeschool.com/courses/rails-for-zombies
Nerian

2
Untuk pembaca selanjutnya, "tabel" adalah "koleksi" di MongoDB. Baris adalah Dokumen, dan Kolom adalah Kolom ... Untuk berjaga-jaga jika Anda tertukar.
cpu_meltdown

65

Bagaimana cara mendesain meja seperti ini di mongodb?

Pertama, untuk memperjelas beberapa konvensi penamaan. MongoDB menggunakan collectionsbukan tables.

Saya pikir tidak ada kunci asing!

Ambil model berikut:

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

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

Jelas daftar kursus Jane menunjuk ke beberapa kursus tertentu. Basis data tidak menerapkan batasan apa pun ke sistem ( yaitu: batasan kunci asing ), jadi tidak ada "penghapusan berjenjang" atau "pembaruan bertingkat". Namun, database memang berisi informasi yang benar.

Selain itu, MongoDB memiliki standar DBRef yang membantu menstandarkan pembuatan referensi ini. Faktanya, jika Anda melihat tautan itu, itu memiliki contoh serupa.

Bagaimana saya bisa menyelesaikan tugas ini?

Agar jelas, MongoDB tidak bersifat relasional. Tidak ada "bentuk normal" standar. Anda harus membuat model database Anda sesuai dengan data yang Anda simpan dan kueri yang ingin Anda jalankan.


2
Oke, tapi bagaimana saya bisa mendapatkan data nama mata kuliah dari koleksi siswa? db.student.find () akan mengembalikan sesuatu seperti kursus: [{course: 'bio101', mark: 85}]
Mark Pegasov

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

Dari mongo doc tentang DBREF: "Kecuali Anda memiliki alasan kuat untuk menggunakan DBRef, gunakan referensi manual sebagai gantinya."
kroiz

23

Kita dapat mendefinisikan apa yang disebut foreign keydi MongoDB. Namun, kami perlu menjaga integritas data SENDIRI . Sebagai contoh,

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

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

The coursesfield berisi _ids kursus. Mudah untuk mendefinisikan hubungan satu-ke-banyak. Namun, jika kita ingin mengambil nama mata kuliah siswa Jane, kita perlu melakukan operasi lain untuk mengambil coursedokumen melalui _id.

Jika kursus bio101dihapus, kita perlu melakukan operasi lain untuk memperbarui coursesbidang di studentdokumen.

Selengkapnya: Desain Skema MongoDB

Sifat MongoDB tipe dokumen mendukung cara-cara fleksibel untuk menentukan hubungan. Untuk menentukan hubungan satu ke banyak:

Dokumen yang disematkan

  1. Cocok untuk satu-ke-sedikit.
  2. Keuntungan: tidak perlu melakukan kueri tambahan ke dokumen lain.
  3. Kerugian: tidak dapat mengelola entitas dokumen yang disematkan secara individual.

Contoh:

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

Referensi anak

Seperti contoh student/ di courseatas.

Referensi orang tua

Cocok untuk one-to-squillions, seperti pesan log.

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
}

Sebenarnya, a hostadalah induk dari a logmsg. Mengacu pada hostid menghemat banyak ruang mengingat bahwa pesan log adalah squillions.

Referensi:

  1. 6 Aturan Thumb untuk Desain Skema MongoDB: Bagian 1
  2. 6 Aturan Thumb untuk Desain Skema MongoDB: Bagian 2
  3. 6 Aturan Thumb untuk Desain Skema MongoDB: Bagian 3
  4. Model Hubungan Satu ke Banyak dengan Referensi Dokumen

19

Dari The Little MongoDB Book

Alternatif lain untuk menggunakan gabungan adalah denormalisasi data Anda. Secara historis, denormalisasi dicadangkan untuk kode yang sensitif terhadap kinerja, atau ketika data harus diambil gambarnya (seperti di log audit). Namun, dengan popularitas NoSQL yang terus berkembang, banyak di antaranya tidak memiliki sambungan, denormalisasi sebagai bagian dari pemodelan normal menjadi semakin umum. Ini tidak berarti Anda harus menduplikasi setiap informasi di setiap dokumen. Namun, daripada membiarkan ketakutan data duplikat mendorong keputusan desain Anda, pertimbangkan untuk membuat model data Anda berdasarkan informasi apa yang termasuk dalam dokumen apa.

Begitu,

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

Jika ini adalah data API RESTful, ganti id kursus dengan tautan GET ke sumber daya kursus


Saya rasa ini adalah jawaban yang benar. Kecuali jika Anda menyimpan data relasional di mongo, dalam hal ini, Anda seharusnya bertanya mengapa Anda menggunakan mongo.
Jay Wick

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.