Mongo'da yabancı anahtarlar?


102

görüntü açıklamasını buraya girin

MongoDB'de böyle bir planı nasıl tasarlarım? Sanırım yabancı anahtar yok!


10
Belge odaklı değil, ilişkisel düşünüyorsunuz. : P
Pat

6
İlişkisel bir veritabanı istiyorsanız neden MongoDB kullanıyorsunuz?
Adam Robinson

50
: D Belge odaklı yöntemi anlamaya çalışıyorum; Bu görevi nasıl çözebilirim?
Mark Pegasov

Belge odaklı düşünme biçiminin cevabını istiyorsanız, stackoverflow.com/a/18637581/80428 adresine bakın . Şu anki kabul edilen cevap işe yarıyor, ancak ilişkisel veritabanını bir belge deposuna kaydırıyor ki bu NoSQL ile ilgili değil.
Jay Wick

Yanıtlar:


29

Mongoid veya MongoMapper gibi bir ORM kullanmak ilginizi çekebilir.

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

MongoDB gibi bir NoSQL veritabanında 'tablolar' değil koleksiyonlar vardır. Belgeler, Koleksiyonlar içinde gruplandırılır. Her türlü veriye sahip her türlü belgeye tek bir koleksiyonda sahip olabilirsiniz. Temel olarak, bir NoSQL veritabanında, verilerin ve varsa ilişkilerinin nasıl düzenleneceğine karar vermek size kalmıştır.

Mongoid ve MongoMapper'ın yaptığı şey, ilişkileri oldukça kolay kurmanız için size uygun yöntemler sağlamaktır. Size verdiğim bağlantıya bakın ve herhangi bir şey sorun.

Düzenle:

Mongoid'de planınızı şöyle yazacaksınız:

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

Düzenle:

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

Belgeler arasında ilişki kurmak için bu ObjectId'yi kullanabilirsiniz.


Öğeleri olan belgeler var ve şehirleri birbirine bağlamak istiyorum. Şehirlerle koleksiyon oluşturuyorum ama şehirleri öğelerle nasıl bağlayacağımı bilmiyorum. PS kötü ingilizcem için üzgünüm.
Mark Pegasov

UPD. PHP'yi programlama dili olarak kullanıyorum, eğer Ruby ile yazılmışsa mongoid'i nasıl kullanabilirim?
Mark Pegasov

1
@ Жирайр Казаросян: Anlıyorum :) Ruby geliştiricisi olmak beni sadece Ruby'de düşündürüyor :) Korkarım ki PHP ve Mongo ile ilgili deneyimim yok, ama şu bağlantıyı kontrol edebilirsiniz: mongodb.org/display/DOCS/ …
Nerian

1
@ Жирайр Казаросян: Ruby on Rails'i pragmatik programcıların Ruby on Rails ile Web geliştirme kitabıyla öğrendim. Ayrıca bu ekran video kaydı kod okulu.com/courses/rails-for-zombies
Nerian

2
Daha sonraki okuyucular için, "tablolar" MongoDB'deki "koleksiyonlardır". Satırlar Belgelerdir ve Sütunlar Alanlardır ... Karışırsanız diye.
cpu_meltdown

67

Mongodb'da böyle bir masa nasıl tasarlanır?

İlk olarak, bazı adlandırma kurallarını açıklığa kavuşturmak. MongoDB collectionsyerine tables.

Sanırım yabancı anahtar yok!

Aşağıdaki modeli alın:

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

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

Açıkça Jane'in kurs listesi bazı belirli kurslara işaret ediyor. Veritabanı sisteme herhangi bir kısıtlama uygulamaz ( yani: yabancı anahtar kısıtlamaları ), bu nedenle "basamaklı silme" veya "basamaklı güncellemeler" yoktur. Ancak, veritabanı doğru bilgileri içerir.

Ek olarak, MongoDB, bu referansların oluşturulmasını standartlaştırmaya yardımcı olan bir DBRef standardına sahiptir. Aslında o bağlantıya bakarsanız, benzer bir örneği var.

Bu görevi nasıl çözebilirim?

Açık olmak gerekirse, MongoDB ilişkisel değildir. Standart bir "normal form" yoktur. Veritabanınızı sakladığınız verilere ve çalıştırmayı düşündüğünüz sorgulara uygun olarak modellemelisiniz.


2
Tamam, ama öğrenci koleksiyonundan ders adı verilerini nasıl alabilirim? db.student.find (), kurslar gibi bir şey döndürecektir: [{course: 'bio101', mark: 85}]
Mark Pegasov

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

Mongo belgeden DBREF hakkında: "DBRefleri kullanmak için ikna edici bir nedeniniz yoksa, bunun yerine manuel referansları kullanın."
kroiz

24

Sözde foreign keyMongoDB'de tanımlayabiliriz . Ancak veri bütünlüğünü KENDİMİZE korumamız gerekiyor . Örneğin,

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

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

coursesAlan içeren _idderslerin s. Bire çok ilişkisini tanımlamak kolaydır. Ancak, öğrencinin ders adlarını almak istiyorsak Jane, coursebelgeyi almak için başka bir işlem yapmamız gerekiyor _id.

Kurs bio101kaldırılırsa, belgedeki coursesalanı güncellemek için başka bir işlem yapmamız gerekir student.

Devamı: MongoDB Şema Tasarımı

MongoDB'nin belge türü yapısı, ilişkileri tanımlamanın esnek yollarını destekler. Bire çok ilişki tanımlamak için:

Gömülü belge

  1. Bire bir için uygundur.
  2. Avantaj: başka bir belgeye ek sorgu yapmaya gerek yoktur.
  3. Dezavantaj: Gömülü belgelerin varlığını ayrı ayrı yönetemez.

Misal:

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

Çocuk referansı

Gibi student/ courseYukarıdaki örnekte.

Ebeveyn referanslama

Günlük mesajları gibi birden çok çizgi için uygundur.

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
}

Gerçekte, a host, a'nın ebeveynidir logmsg. Referanslanma hostid günlük mesajlarını squillions olduğu göz önüne alındığında fazla yer kazandırır.

Referanslar:

  1. MongoDB Şema Tasarımı için 6 Temel Kural: Bölüm 1
  2. MongoDB Şema Tasarımı için 6 Temel Kural: Bölüm 2
  3. MongoDB Şema Tasarımı için 6 Temel Kural: Bölüm 3
  4. Belge Referanslarıyla Bire Çoğa İlişki Modelleyin

19

Gönderen Küçük MongoDB Kitabı

Birleştirme kullanmanın bir başka alternatifi de verilerinizi normalden farklı hale getirmektir. Tarihsel olarak, normalden arındırma performansa duyarlı kod için veya verilerin ne zaman anlık görüntülenmesi gerektiği (bir denetim günlüğünde olduğu gibi) için ayrılmıştı. Bununla birlikte, çoğu birleşme içermeyen NoSQL'in gittikçe artan popülaritesi ile normal modellemenin bir parçası olarak normal olmayanlaştırma giderek yaygınlaşmaktadır. Bu, her belgedeki her bilgiyi kopyalamanız gerektiği anlamına gelmez. Ancak, yinelenen veri korkusunun tasarım kararlarınızı yönlendirmesine izin vermek yerine, verilerinizi hangi bilgilerin hangi belgeye ait olduğuna göre modellemeyi düşünün.

Yani,

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

RESTful API verisi ise, kurs kimliğini kurs kaynağına giden bir GET bağlantısıyla değiştirin


Bunun doğru cevap olduğunu düşünüyorum. İlişkisel verileri mongo'da depolamadığınız sürece, bu durumda, neden mongo kullandığınızı gerçekten sorgulamalısınız .
Jay Wick

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.