Fremdschlüssel im Mongo?

93

Geben Sie hier die Bildbeschreibung ein

Wie entwerfe ich ein solches Schema in MongoDB? Ich denke es gibt keine Fremdschlüssel!

Mark Pegasov
quelle
9
Sie denken relational statt dokumentenorientiert. : P
Pat
6
Warum verwenden Sie MongoDB, wenn Sie eine relationale Datenbank möchten?
Adam Robinson
47
: D Ich versuche, dokumentenorientierte Methoden zu verstehen. Wie kann ich diese Aufgabe lösen?
Mark Pegasov
Wenn Sie die Antwort auf die dokumentenorientierte Denkweise wünschen, lesen Sie stackoverflow.com/a/18637581/80428 . Die aktuell akzeptierte Antwort funktioniert, ist jedoch eine relationale Datenbank für einen Dokumentenspeicher, um die es bei NoSQL nicht geht.
Jay Wick

Antworten:

27

Möglicherweise möchten Sie ein ORM wie Mongoid oder MongoMapper verwenden.

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

In einer NoSQL-Datenbank wie MongoDB gibt es keine 'Tabellen', sondern Sammlungen. Dokumente werden in Sammlungen gruppiert. Sie können jede Art von Dokument - mit jeder Art von Daten - in einer einzigen Sammlung haben. Grundsätzlich liegt es in einer NoSQL-Datenbank an Ihnen, zu entscheiden, wie die Daten und ihre Beziehungen, falls vorhanden, organisiert werden sollen.

Mongoid und MongoMapper bieten Ihnen bequeme Methoden zum einfachen Einrichten von Beziehungen. Schauen Sie sich den Link an, den ich Ihnen gegeben habe, und fragen Sie etwas.

Bearbeiten:

In Mongoid schreiben Sie Ihr Schema wie folgt:

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

Bearbeiten:

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

Sie können diese ObjectId verwenden, um Beziehungen zwischen Dokumenten herzustellen.

Nerian
quelle
Es gibt Dokumente mit Gegenständen, und ich möchte Städte binden. Ich habe eine Sammlung mit Städten erstellt, weiß aber nicht, wie ich Städte mit Gegenständen verbinden soll. PS Entschuldigung für mein schlechtes Englisch.
Mark Pegasov
UPD. Ich verwende PHP als Programmiersprache. Wie kann ich Mongoid verwenden, wenn es in Ruby geschrieben ist?
Mark Pegasov
1
@ Жирайр Казаросян: Oh, ich verstehe :) Als Ruby-Entwickler denke ich nur an Ruby :) Ich fürchte, ich habe keine Erfahrung mit PHP und Mongo, aber Sie können diesen Link überprüfen: mongodb.org/display/DOCS/ …
Nerian
1
@ Жирайр Казаросян: Ich habe Ruby on Rails mit dem Buch Web Development with Ruby on Rails von den pragmatischen Programmierern gelernt. Sie können auch eine kostenlose Einführung mit diesem Screencast erhalten. Codeschool.com/courses/rails-for-zombies
Nerian
2
Für spätere Leser sind die "Tabellen" "Sammlungen" in MongoDB. Zeilen sind Dokumente und Spalten sind Felder ... Nur für den Fall, dass Sie durcheinander geraten.
cpu_meltdown
64

Wie entwerfe ich einen solchen Tisch in Mongodb?

Erstens, um einige Namenskonventionen zu klären. MongoDB verwendet collectionsanstelle von tables.

Ich denke es gibt keine Fremdschlüssel!

Nehmen Sie das folgende Modell:

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

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

Die Kursliste von Jane weist eindeutig auf bestimmte Kurse hin. Die Datenbank wendet keine Einschränkungen auf das System an ( dh Fremdschlüsseleinschränkungen ), daher gibt es keine "kaskadierenden Löschvorgänge" oder "kaskadierenden Aktualisierungen". Die Datenbank enthält jedoch die richtigen Informationen.

Darüber hinaus verfügt MongoDB über einen DBRef-Standard , mit dessen Hilfe die Erstellung dieser Referenzen standardisiert werden kann. Wenn Sie sich diesen Link ansehen, gibt es ein ähnliches Beispiel.

Wie kann ich diese Aufgabe lösen?

Um klar zu sein, ist MongoDB nicht relational. Es gibt keine Standard "Normalform". Sie sollten Ihre Datenbank entsprechend den von Ihnen gespeicherten Daten und den Abfragen modellieren, die Sie ausführen möchten.

Gates VP
quelle
2
Ok, aber wie kann ich Cource-Namensdaten aus der Studentensammlung erhalten? db.student.find () gibt so etwas wie Kurse zurück: [{Kurs: 'bio101', Note: 85}]
Mark Pegasov
@ Жирайр Казаросян:> db.foo.find ({'_ id': ObjectId ("4df6539ae90592692ccc9940")}) -------------> {"_id": ObjectId ("4df6539ae90592692ccc9940"), "Gruppe": "Telefone"}
Nerian
Aus mongo doc über DBREF: "Wenn Sie keinen zwingenden Grund haben, DBRefs zu verwenden, verwenden Sie stattdessen manuelle Referenzen."
Kroiz
22

Wir können das sogenannte foreign keyin MongoDB definieren. Allerdings müssen wir die Datenintegrität erhalten von uns . Beispielsweise,

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

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

Das coursesFeld enthält _ids von Kursen. Es ist einfach, eine Eins-zu-Viele-Beziehung zu definieren. Wenn wir jedoch die Kursnamen des Studenten abrufen möchten Jane, müssen wir einen weiteren Vorgang ausführen, um das courseDokument über abzurufen _id.

Wenn der Kurs bio101entfernt wird, müssen wir einen weiteren Vorgang ausführen, um das coursesFeld im studentDokument zu aktualisieren .

Mehr: MongoDB Schema Design

Die dokumenttypisierte Natur von MongoDB unterstützt flexible Möglichkeiten zum Definieren von Beziehungen. So definieren Sie eine Eins-zu-Viele-Beziehung:

Eingebettetes Dokument

  1. Geeignet für eins zu wenige.
  2. Vorteil: Es müssen keine zusätzlichen Abfragen für ein anderes Dokument durchgeführt werden.
  3. Nachteil: Die Entität eingebetteter Dokumente kann nicht einzeln verwaltet werden.

Beispiel:

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

Kinderreferenzierung

Wie das student/ courseBeispiel oben.

Übergeordnete Referenzierung

Geeignet für Eins-zu-Billionen, wie z. B. Protokollnachrichten.

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
}

A ist praktisch hostdas Elternteil von a logmsg. Das Verweisen auf die hostID spart viel Platz, da die Protokollnachrichten Billionen sind.

Verweise:

  1. 6 Faustregeln für das MongoDB-Schemadesign: Teil 1
  2. 6 Faustregeln für das MongoDB-Schemadesign: Teil 2
  3. 6 Faustregeln für das MongoDB-Schemadesign: Teil 3
  4. Modellieren Sie Eins-zu-Viele-Beziehungen mit Dokumentreferenzen
Freude
quelle
19

Aus dem kleinen MongoDB-Buch

Eine weitere Alternative zur Verwendung von Joins besteht darin, Ihre Daten zu denormalisieren. In der Vergangenheit war die Denormalisierung für leistungsabhängigen Code reserviert oder für den Fall, dass Daten als Snapshots erstellt werden sollten (wie in einem Überwachungsprotokoll). Mit der stetig wachsenden Popularität von NoSQL, von denen viele keine Verknüpfungen haben, wird die Denormalisierung als Teil der normalen Modellierung immer häufiger. Dies bedeutet nicht, dass Sie jede Information in jedem Dokument duplizieren sollten. Anstatt die Angst vor doppelten Daten Ihre Entwurfsentscheidungen bestimmen zu lassen, sollten Sie Ihre Daten anhand der Informationen modellieren, die zu welchem ​​Dokument gehören.

So,

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

Wenn es sich um RESTful-API-Daten handelt, ersetzen Sie die Kurs-ID durch einen GET-Link zur Kursressource

ZAky
quelle
Ich denke das ist die richtige Antwort. Wenn Sie keine relationalen Daten in Mongo speichern, sollten Sie sich in diesem Fall wirklich fragen, warum Sie Mongo verwenden.
Jay Wick
0

Der Zweck von ForeignKey besteht darin, die Erstellung von Daten zu verhindern, wenn der Feldwert nicht mit dem ForeignKey übereinstimmt. Um dies in MongoDB zu erreichen, verwenden wir Schema-Middlewares, die die Datenkonsistenz sicherstellen.

Bitte schauen Sie sich die Dokumentation an. https://mongoosejs.com/docs/middleware.html#pre

Ahmet Emrebas
quelle