Klucze obce w Mongo?

97

wprowadź opis obrazu tutaj

Jak zaprojektować taki schemat w MongoDB? Myślę, że nie ma kluczy obcych!

Mark Pegasov
źródło
10
Myślisz relacyjnie, zamiast skupiać się na dokumentach. : P
Pat
6
Dlaczego używasz MongoDB, jeśli chcesz mieć relacyjną bazę danych?
Adam Robinson
48
: D Próbuję zrozumieć metodę zorientowaną na dokument; Jak mogę rozwiązać to zadanie?
Mark Pegasov
Jeśli szukasz odpowiedzi na sposób myślenia zorientowany na dokument, zobacz stackoverflow.com/a/18637581/80428 . Obecnie przyjęta odpowiedź działa, ale przenosi relacyjną bazę danych do magazynu dokumentów, a nie o to chodzi w NoSQL.
Jay Wick

Odpowiedzi:

27

Możesz być zainteresowany użyciem ORM, takiego jak Mongoid lub MongoMapper.

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

W bazie danych NoSQL, takiej jak MongoDB, nie ma „tabel”, ale kolekcje. Dokumenty są pogrupowane w Kolekcje. Możesz mieć dowolny dokument - z dowolnymi danymi - w jednej kolekcji. Zasadniczo, w bazie danych NoSQL to Ty decydujesz, jak zorganizować dane i ich relacje, jeśli takie istnieją.

To, co robią Mongoid i MongoMapper, to zapewnienie wygodnych metod łatwego konfigurowania relacji. Sprawdź link, który ci dałem i zapytaj o wszystko.

Edytować:

W Mongoid napiszesz swój schemat w ten sposób:

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

Edytować:

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

Możesz użyć tego ObjectId do tworzenia relacji między dokumentami.

Nerian
źródło
Jest dokument z przedmiotami i chcę wiązać miasta. Tworzę kolekcje z miastami, ale nie wiem, jak wiązać miasta przedmiotami. PS przepraszam za mój zły angielski.
Mark Pegasov
UPD. Używam PHP jako języka programowania, jak mogę używać mongoid, jeśli jest napisany w języku Ruby?
Mark Pegasov
1
@ Жирайр Казаросян: Aha rozumiem :) Będąc programistą Rubiego myślę tylko w Rubim :) Obawiam się, że nie mam doświadczenia z PHP i Mongo, ale możesz sprawdzić ten link: mongodb.org/display/DOCS/ …
Nerian
1
@ Жирайр Казаросян: Uczyłem się Ruby on Rails z książką Web development with Ruby on Rails autorstwa pragmatycznych programistów. Można również uzyskać wstęp za darmo z tego screencast codeschool.com/courses/rails-for-zombies
Nerian
2
Dla późniejszych czytelników „tabele” to „kolekcje” w MongoDB. Wiersze to dokumenty, a kolumny to pola ... Na wszelki wypadek, gdybyś się pomylił.
cpu_meltdown
65

Jak zaprojektować taką tabelę w Mongodb?

Po pierwsze, aby wyjaśnić pewne konwencje nazewnictwa. MongoDB używa collectionszamiast tables.

Myślę, że nie ma kluczy obcych!

Weź następujący model:

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

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

Najwyraźniej lista kursów Jane wskazuje na określone kursy. Baza danych nie nakłada żadnych ograniczeń na system ( np. Ograniczenia klucza obcego ), więc nie ma „kaskadowego usuwania” ani „kaskadowych aktualizacji”. Jednak baza danych zawiera poprawne informacje.

Ponadto MongoDB ma standard DBRef, który pomaga ujednolicić tworzenie tych odniesień. W rzeczywistości, jeśli spojrzysz na ten link, ma on podobny przykład.

Jak mogę rozwiązać to zadanie?

Żeby było jasne, MongoDB nie jest relacyjne. Nie ma standardowej „postaci normalnej”. Bazę danych należy modelować odpowiednio do przechowywanych danych i zapytań, które zamierzasz uruchamiać.

Gates VP
źródło
2
Ok, ale jak mogę uzyskać dane dotyczące nazwiska kurierskiego z kolekcji studentów? db.student.find () zwróci coś w rodzaju kursów: [{course: 'bio101', mark: 85}]
Mark Pegasov
@ Жирайр Казаросян:> db.foo.find ({'_ id': ObjectId ("4df6539ae90592692ccc9940")}) -------------> {"_id": ObjectId ("4df6539ae90592692ccc9940"), "group": "telefony"}
Nerian
Z dokumentu mongo o DBREF: „Jeśli nie masz nieodpartego powodu, aby używać DBRefs, użyj zamiast tego ręcznych odwołań”.
kroiz
23

foreign keyW MongoDB możemy zdefiniować tzw . Jednak musimy sami dbać o integralność danych . Na przykład,

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

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

coursesPole zawiera _ids kursów. Łatwo jest zdefiniować relację jeden do wielu. Jeśli jednak chcemy pobrać nazwy kursów uczniów Jane, musimy wykonać inną operację, aby pobrać coursedokument za pośrednictwem _id.

Jeśli kurs bio101zostanie usunięty, musimy wykonać kolejną operację, aby zaktualizować coursespole w studentdokumencie.

Więcej: Projekt schematu MongoDB

Typ dokumentu MongoDB obsługuje elastyczne sposoby definiowania relacji. Aby zdefiniować relację jeden do wielu:

Dokument osadzony

  1. Odpowiedni dla kilku osób.
  2. Zaleta: nie ma potrzeby wykonywania dodatkowych zapytań do innego dokumentu.
  3. Wada: nie można indywidualnie zarządzać jednostką osadzonych dokumentów.

Przykład:

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

Odniesienia do dzieci

Podobnie jak student/course przykładzie powyżej.

Odniesienia do rodziców

Odpowiedni dla jednego do squillions, takich jak komunikaty dziennika.

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
}

Praktycznie a hostjest rodzicem logmsg. Odwołanie się dohost identyfikatora oszczędza dużo miejsca, biorąc pod uwagę, że komunikaty dziennika to miliardy.

Bibliografia:

  1. 6 praktycznych zasad projektowania schematu MongoDB: część 1
  2. 6 praktycznych zasad projektowania schematu MongoDB: część 2
  3. 6 praktycznych zasad projektowania schematu MongoDB: część 3
  4. Modeluj relacje jeden do wielu z odwołaniami do dokumentów
Radość
źródło
19

Z książki The Little MongoDB

Jeszcze inną alternatywą dla używania sprzężeń jest denormalizacja danych. W przeszłości denormalizacja była zarezerwowana dla kodu wrażliwego na wydajność lub kiedy dane powinny być migawkowe (jak w dzienniku audytu). Jednak wraz ze stale rosnącą popularnością NoSQL, z których wiele nie ma połączeń, denormalizacja jako część normalnego modelowania staje się coraz bardziej powszechna. Nie oznacza to, że powinieneś powielać każdą informację w każdym dokumencie. Jednak zamiast pozwolić, aby strach przed powieleniem danych wpływał na decyzje projektowe, rozważ modelowanie danych w oparciu o informacje, które należą do danego dokumentu.

Więc,

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

Jeśli są to dane RESTful API, zamień identyfikator kursu na łącze GET do zasobu kursu

ZAky
źródło
Myślę, że to jest poprawna odpowiedź. O ile nie przechowujesz danych relacyjnych w mongo, w takim przypadku naprawdę powinieneś zapytać, dlaczego używasz mongo.
Jay Wick
0

Celem ForeignKey jest zapobieganie tworzeniu danych, jeśli wartość pola nie jest zgodna z jego ForeignKey. Aby to osiągnąć w MongoDB, używamy oprogramowania pośredniego Schema, które zapewnia spójność danych.

Zapoznaj się z dokumentacją. https://mongoosejs.com/docs/middleware.html#pre

Ahmet Emrebas
źródło