Chiavi esterne in mongo?


96

inserisci qui la descrizione dell'immagine

Come si progetta uno schema come questo in MongoDB? Penso che non ci siano chiavi esterne!


9
Stai pensando in modo relazionale, invece che orientato ai documenti. : P
Pat

6
Perché stai usando MongoDB se vuoi un database relazionale?
Adam Robinson

48
: D Sto cercando di capire il metodo orientato ai documenti; Come posso risolvere questo compito?
Mark Pegasov

Se vuoi la risposta al modo di pensare orientato ai documenti, consulta stackoverflow.com/a/18637581/80428 . La risposta attualmente accettata funziona ma è il database relazionale di shoehorning per un archivio di documenti che non è ciò di cui si occupa NoSQL.
Jay Wick

Risposte:


27

Potresti essere interessato a utilizzare un ORM come Mongoid o MongoMapper.

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

In un database NoSQL come MongoDB non ci sono "tabelle" ma raccolte. I documenti sono raggruppati all'interno delle raccolte. Puoi avere qualsiasi tipo di documento, con qualsiasi tipo di dati, in un'unica raccolta. In pratica, in un database NoSQL sta a te decidere come organizzare i dati e le loro relazioni, se ce ne sono.

Quello che fanno Mongoid e MongoMapper è fornire metodi convenienti per impostare le relazioni abbastanza facilmente. Controlla il link che ti ho fornito e chiedi qualsiasi cosa.

Modificare:

In mongoid scriverai il tuo schema in questo modo:

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

Modificare:

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

È possibile utilizzare tale ObjectId per creare relazioni tra i documenti.


Ci sono documenti con oggetti e voglio vincolare le città. Ho creato collezioni con le città, ma non so come unire le città con gli oggetti. PS scusa per il mio cattivo inglese.
Mark Pegasov

UPD. Sto usando PHP come linguaggio di programmazione, come posso usare mongoid, se è scritto in Ruby?
Mark Pegasov

1
@ Жирайр Казаросян: Oh capisco :) Essere uno sviluppatore Ruby mi fa pensare solo in Ruby :) Temo di non avere esperienza con PHP e Mongo, ma puoi controllare questo link: mongodb.org/display/DOCS/ ...
Nerian

1
@ Жирайр Казаросян: Ho imparato Ruby on Rails con il libro Web development with Ruby on Rails, dai pragmatici programmatori. Puoi anche ottenere un'introduzione gratuita con questo screencast codeschool.com/courses/rails-for-zombies
Nerian

2
Per i lettori successivi, le "tabelle" sono "raccolte" in MongoDB. Le righe sono documenti e le colonne sono campi ... Nel caso in cui ti confondi.
cpu_meltdown

65

Come progettare un tavolo come questo a Mongodb?

Primo, per chiarire alcune convenzioni di denominazione. MongoDB utilizza collectionsinvece di tables.

Penso che non ci siano chiavi esterne!

Prendi il seguente modello:

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

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

Chiaramente l'elenco dei corsi di Jane punta ad alcuni corsi specifici. Il database non applica alcun vincolo al sistema (ad esempio: vincoli di chiave esterna ), quindi non ci sono "eliminazioni a cascata" o "aggiornamenti a cascata". Tuttavia, il database contiene le informazioni corrette.

Inoltre, MongoDB ha uno standard DBRef che aiuta a standardizzare la creazione di questi riferimenti. In effetti, se dai un'occhiata a quel link, ha un esempio simile.

Come posso risolvere questo compito?

Per essere chiari, MongoDB non è relazionale. Non esiste una "forma normale" standard. È necessario modellare il database in modo appropriato ai dati archiviati e alle query che si intende eseguire.


2
Ok, ma come posso ottenere i dati del nome cortese dalla raccolta degli studenti? db.student.find () restituirà qualcosa di simile a corsi: [{course: 'bio101', mark: 85}]
Mark Pegasov

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

Da mongo doc su DBREF: "A meno che tu non abbia una ragione convincente per usare DBRefs, usa invece riferimenti manuali."
kroiz

23

Possiamo definire il cosiddetto foreign keyin MongoDB. Tuttavia, dobbiamo mantenere l'integrità dei dati DA NOI STESSI . Per esempio,

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

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

Il coursescampo contiene _idi corsi. È facile definire una relazione uno-a-molti. Tuttavia, se vogliamo recuperare i nomi dei corsi degli studenti Jane, dobbiamo eseguire un'altra operazione per recuperare il coursedocumento tramite _id.

Se il corso bio101viene rimosso, dobbiamo eseguire un'altra operazione per aggiornare il coursescampo nel filestudent documento.

Altro: MongoDB Schema Design

La natura tipizzata da documento di MongoDB supporta modi flessibili per definire le relazioni. Per definire una relazione uno-a-molti:

Documento incorporato

  1. Adatto per uno-pochi.
  2. Vantaggio: non è necessario eseguire query aggiuntive su un altro documento.
  3. Svantaggio: non è possibile gestire individualmente l'entità dei documenti incorporati.

Esempio:

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

Riferimento ai bambini

Come l' esempio student/ coursesopra.

Riferimento genitore

Adatto per one-to-squillions, come i messaggi di registro.

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
}

Virtualmente, a hostè il genitore di a logmsg. Fare riferimento hostall'ID consente di risparmiare molto spazio dato che i messaggi di log sono squillioni.

Riferimenti:

  1. 6 Regole pratiche per MongoDB Schema Design: Parte 1
  2. 6 Regole pratiche per MongoDB Schema Design: Parte 2
  3. 6 Regole pratiche per MongoDB Schema Design: Parte 3
  4. Modello di relazioni uno-a-molti con riferimenti ai documenti

19

Dal libro The Little MongoDB

Un'altra alternativa all'uso dei join è denormalizzare i dati. Storicamente, la denormalizzazione era riservata al codice sensibile alle prestazioni o quando i dati dovevano essere snapshot (come in un registro di controllo). Tuttavia, con la popolarità sempre crescente di NoSQL, molti dei quali non hanno join, la denormalizzazione come parte della modellazione normale sta diventando sempre più comune. Questo non significa che dovresti duplicare ogni informazione in ogni documento. Tuttavia, anziché lasciare che la paura dei dati duplicati guidi le tue decisioni di progettazione, considera la possibilità di modellare i dati in base alle informazioni che appartengono a quale documento.

Così,

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

Se si tratta di dati API RESTful, sostituire l'ID del corso con un collegamento GET alla risorsa del corso


Penso che questa sia la risposta corretta. A meno che tu non stia archiviando dati relazionali in mongo, nel qual caso dovresti davvero chiederti perché stai usando mongo.
Jay Wick

0

Lo scopo di ForeignKey è impedire la creazione di dati se il valore del campo non corrisponde alla sua ForeignKey. Per ottenere ciò in MongoDB, utilizziamo middleware Schema che garantiscono la coerenza dei dati.

Si prega di dare un'occhiata alla documentazione. https://mongoosejs.com/docs/middleware.html#pre

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.