Clés étrangères à Mongo?

95

entrez la description de l'image ici

Comment concevoir un tel schéma dans MongoDB? Je pense qu'il n'y a pas de clés étrangères!

Mark Pegasov
la source
9
Vous pensez relationnellement, au lieu d'être orienté document. : P
Pat
6
Pourquoi utilisez-vous MongoDB si vous voulez une base de données relationnelle?
Adam Robinson
48
: D J'essaie de comprendre la méthode orientée document; Comment puis-je résoudre cette tâche?
Mark Pegasov
Si vous voulez la réponse à la façon de penser orientée document, consultez stackoverflow.com/a/18637581/80428 . La réponse actuellement acceptée fonctionne, mais consiste à associer une base de données relationnelle à un magasin de documents, ce qui n'est pas l'objet de NoSQL.
Jay Wick

Réponses:

27

Vous pourriez être intéressé par l'utilisation d'un ORM comme Mongoid ou MongoMapper.

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

Dans une base de données NoSQL comme MongoDB, il n'y a pas de «tables» mais des collections. Les documents sont regroupés dans les collections. Vous pouvez avoir n'importe quel type de document - avec n'importe quel type de données - dans une seule collection. Fondamentalement, dans une base de données NoSQL, c'est à vous de décider comment organiser les données et leurs relations, s'il y en a.

Ce que font Mongoid et MongoMapper est de vous fournir des méthodes pratiques pour établir des relations assez facilement. Consultez le lien que je vous ai donné et demandez n'importe quoi.

Éditer:

En mongoïde, vous écrirez votre schéma comme ceci:

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

Éditer:

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

Vous pouvez utiliser cet ObjectId pour établir des relations entre des documents.

Nerian
la source
Il y a un document avec des éléments, et je veux lier des villes. J'ai créé une collection avec des villes, mais je ne sais pas comment lier des villes avec des objets. PS désolé pour mon mauvais anglais.
Mark Pegasov
UPD. J'utilise PHP comme langage de programmation, comment puis-je utiliser mongoid, s'il est écrit en Ruby?
Mark Pegasov
1
@ Жирайр Казаросян: Oh je vois :) Être développeur Ruby me fait penser uniquement à Ruby :) J'ai peur de ne pas avoir d'expérience avec PHP et Mongo, mais vous pouvez consulter ce lien: mongodb.org/display/DOCS/ …
Nerian
1
@ Жирайр Казаросян: J'ai appris Ruby on Rails avec le livre Développement Web avec Ruby on Rails, par les programmeurs pragmatiques. Vous pouvez également obtenir une introduction gratuitement avec ce screencast codeschool.com/courses/rails-for-zombies
Nerian
2
Pour les lecteurs ultérieurs, les «tables» sont des «collections» dans MongoDB. Les lignes sont des documents et les colonnes sont des champs ... Juste au cas où vous seriez mélangé.
cpu_meltdown
65

Comment concevoir une table comme celle-ci dans Mongodb?

Tout d'abord, pour clarifier certaines conventions de dénomination. MongoDB utilise à la collectionsplace de tables.

Je pense qu'il n'y a pas de clés étrangères!

Prenez le modèle suivant:

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

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

Il est clair que la liste de cours de Jane pointe vers des cours spécifiques. La base de données n'applique aucune contrainte au système ( c'est-à-dire: contraintes de clé étrangère ), il n'y a donc pas de "suppressions en cascade" ou de "mises à jour en cascade". Cependant, la base de données contient les informations correctes.

De plus, MongoDB dispose d'un standard DBRef qui permet de standardiser la création de ces références. En fait, si vous regardez ce lien, il a un exemple similaire.

Comment puis-je résoudre cette tâche?

Pour être clair, MongoDB n'est pas relationnel. Il n'y a pas de "forme normale" standard. Vous devez modéliser votre base de données en fonction des données que vous stockez et des requêtes que vous souhaitez exécuter.

Vice-président Gates
la source
2
OK, mais comment puis-je obtenir des données sur les noms de cours à partir de la collection des élèves? db.student.find () retournera quelque chose comme des cours: [{cours: 'bio101', note: 85}]
Mark Pegasov
@ Жирайр Казаросян:> db.foo.find ({'_ id': ObjectId ("4df6539ae90592692ccc9940")}) -------------> {"_id": ObjectId ("4df6539ae90592692ccc9940"), "group": "phones"}
Nerian
De mongo doc à propos de DBREF: "Sauf si vous avez une raison impérieuse d'utiliser DBRefs, utilisez plutôt des références manuelles."
kroiz
23

Nous pouvons définir ce que l'on appelle foreign keydans MongoDB. Cependant, nous devons maintenir l'intégrité des données PAR NOUS . Par exemple,

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

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

Le courseschamp contient _iddes cours. Il est facile de définir une relation un-à-plusieurs. Cependant, si nous voulons récupérer les noms de cours des étudiants Jane, nous devons effectuer une autre opération pour récupérer le coursedocument via _id.

Si le cours bio101est supprimé, nous devons effectuer une autre opération pour mettre à jour le courseschamp dans le studentdocument.

Plus: Conception de schéma MongoDB

La nature de type document de MongoDB prend en charge des méthodes flexibles pour définir les relations. Pour définir une relation un-à-plusieurs:

Document intégré

  1. Convient pour un à quelques-uns.
  2. Avantage: pas besoin d'effectuer des requêtes supplémentaires sur un autre document.
  3. Inconvénient: impossible de gérer l'entité des documents incorporés individuellement.

Exemple:

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

Référencement enfant

Comme l' exemple student/ courseci-dessus.

Référencement parent

Convient pour les one-to-squillions, tels que les messages de journal.

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
}

Pratiquement, a hostest le parent de a logmsg. hostFaire référence à l' id économise beaucoup d'espace étant donné que les messages du journal sont des squillions.

Références:

  1. 6 règles de base pour la conception de schémas MongoDB: partie 1
  2. 6 règles de base pour la conception de schémas MongoDB: partie 2
  3. 6 règles de base pour la conception de schémas MongoDB: partie 3
  4. Modèles de relations un à plusieurs avec des références de document
Joie
la source
19

Tiré du petit livre MongoDB

Une autre alternative à l'utilisation des jointures consiste à dénormaliser vos données. Historiquement, la dénormalisation était réservée au code sensible aux performances, ou lorsque les données devaient être instantanées (comme dans un journal d'audit). Cependant, avec la popularité croissante de NoSQL, dont beaucoup n'ont pas de jointure, la dénormalisation dans le cadre de la modélisation normale devient de plus en plus courante. Cela ne signifie pas que vous devez dupliquer toutes les informations dans chaque document. Cependant, plutôt que de laisser la peur des données dupliquées guider vos décisions de conception, envisagez de modéliser vos données en fonction des informations appartenant à quel document.

Alors,

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

S'il s'agit d'une donnée d'API RESTful, remplacez l'ID de cours par un lien GET vers la ressource de cours

ZAky
la source
Je pense que c'est la bonne réponse. À moins que vous ne stockiez des données relationnelles dans mongo, auquel cas, vous auriez vraiment dû vous demander pourquoi vous utilisez mongo.
Jay Wick
0

Le but de ForeignKey est d'empêcher la création de données si la valeur du champ ne correspond pas à sa ForeignKey. Pour ce faire dans MongoDB, nous utilisons des middlewares Schema qui garantissent la cohérence des données.

Veuillez consulter la documentation. https://mongoosejs.com/docs/middleware.html#pre

Ahmet Emrebas
la source