120 votes

Clés étrangères dans Mongo ?

enter image description here

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

12 votes

Vous pensez de manière relationnelle, au lieu d'être orienté vers les documents. :P

11 votes

Pourquoi utilisez-vous MongoDB si vous voulez une base de données relationnelle ?

63 votes

:D J'essaie de comprendre la méthode orientée vers les documents ; comment puis-je résoudre cette tâche ?

73voto

Gates VP Points 26481

Comment concevoir une table comme celle-ci dans mongodb ?

Tout d'abord, il convient de clarifier certaines conventions de dénomination. MongoDB utilise collections au lieu de tables .

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

Prenons 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 renvoie à certains cours spécifiques. La base de données n'applique aucune contrainte au système ( c.-à-d. : 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.

En outre, MongoDB dispose d'un Norme DBRef qui permet de normaliser la création de ces références. En fait, si vous jetez un coup d'œil à ce lien, vous y trouverez un exemple similaire.

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

Pour être clair, MongoDB n'est pas relationnel. Il n'existe 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 comptez exécuter.

2 votes

Ok, mais comment puis-je obtenir les données de nom de cours à partir de la collection d'étudiants ? db.student.find() retournera quelque chose comme cours : [ {cours : 'bio101', note : 85 } ]

0 votes

@ : > db.foo.find({'_id':ObjectId("4df6539ae90592692ccc9940")}) -------------> { "_id" : ObjectId("4df6539ae90592692ccc9940"), "group" : "phones" }

0 votes

Extrait de la doc de Mongo sur les DBREF : "A moins que vous n'ayez une raison impérieuse d'utiliser DBRefs, utilisez plutôt des références manuelles".

34voto

Nerian Points 6733

Vous pouvez ê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 des 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, le cas échéant.

Mongoid et MongoMapper proposent des méthodes pratiques pour établir des relations assez facilement. Consultez le lien que je vous ai donné et demandez ce que vous voulez.

Edit :

Dans Mongoid, 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

Edit :

> 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 afin d'établir des relations entre les documents.

0 votes

Il y a un document avec des articles, et je veux lier les villes. J'ai créé une collection avec les villes, mais je ne sais pas comment lier les villes aux articles. PS : désolé pour mon mauvais anglais.

0 votes

UPD. J'utilise PHP comme langage de programmation, comment puis-je utiliser mongoid, s'il est écrit en Ruby ?

1 votes

@ : Oh je vois :) Le fait d'être un développeur Ruby me fait penser uniquement en Ruby :) J'ai peur de ne pas avoir d'expérience avec PHP et Mongo, mais vous pouvez vérifier ce lien : mongodb.org/display/DOCS/

31voto

Joy Points 6712

Nous pouvons définir le soi-disant foreign key dans MongoDB. Cependant, nous devons maintenir l'intégrité des données PAR NOUS-MÊMES . Par exemple,

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

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

El courses Le champ contient _id de cours. Il est facile de définir une relation de type "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 l'adresse de l'utilisateur. course document via _id .

Si le cours bio101 est supprimée, nous devons effectuer une autre opération pour mettre à jour le fichier courses dans le champ student document.

Plus : Conception des schémas de MongoDB

La nature typée document de MongoDB permet de définir les relations de manière flexible. Pour définir une relation de type un à plusieurs :

Document incorporé

  1. Convient pour une à deux personnes.
  2. Avantage : il n'est pas nécessaire d'effectuer des requêtes supplémentaires sur un autre document.
  3. Inconvénient : ne peut pas gérer individuellement l'entité des documents intégrés.

Ejemplo:

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 des enfants

Comme le student / course exemple ci-dessus.

Référencement des parents

Convient pour un à plusieurs millions, comme les messages du 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
}

Virtuellement, un host est le parent d'un logmsg . Référence à la host id permet de gagner beaucoup d'espace étant donné que les messages du journal sont des squillions.

Références :

  1. 6 règles d'or pour la conception de schémas MongoDB : 1ère partie
  2. 6 règles d'or pour la conception de schémas MongoDB : Partie 2
  3. 6 règles d'or pour la conception de schémas MongoDB : 3ème partie
  4. Modélisation des relations un-à-plusieurs avec des références de documents

0 votes

Il n'est pas aussi facile de faire respecter manuellement la contrainte FK. Pensez aux mises à jour simultanées.

22voto

ZAky Points 62

Desde Le petit livre de 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 doivent être instantanées (comme dans un journal d'audit). Cependant, avec la popularité croissante de NoSQL, de nombreux Cependant, avec la popularité croissante de NoSQL, dont beaucoup n'ont pas de jointures, la dénormalisation dans le cadre de la modélisation normale devient de plus en plus courante. de plus en plus courante. Cela ne signifie pas que vous devez dupliquer chaque élément d'information dans chaque document. Cependant, Cependant, plutôt que de laisser la peur de la duplication des données guider vos décisions de conception, envisagez de modéliser vos données en fonction des informations qui appartiennent à chaque document. informations appartiennent à tel ou tel document.

Donc,

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

S'il s'agit de données RESTful API, remplacez l'identifiant du cours par un lien GET vers la ressource du cours.

0 votes

Je pense que c'est la bonne réponse. A moins que vous ne stockiez des données relationnelles dans Mongo, auquel cas, vous devriez vraiment vous poser la question suivante pourquoi vous utilisez Mongo.

0 votes

Hmm, l'existence de doublons ou de références n'est pas exactement une propriété des bases de données relationnelles. C'est une propriété de la réalité. Je suppose que l'ACID est peut-être une propriété de la base de données relationnelle qui est supposée ici.

3voto

Efrain Points 1014

Réponse courte : Vous devez utiliser des "références faibles" entre les collections, en utilisant les propriétés ObjectId :

Les références stockent les relations entre les données en incluant des liens ou des références d'un document à un autre. Les applications peuvent résoudre ces références pour accéder aux données correspondantes. En gros, il s'agit de modèles de données normalisés.

https://docs.mongodb.com/manual/core/data-modeling-introduction/#references

Bien entendu, cela ne vérifiera pas l'intégrité référentielle. Vous devez gérer les "liens morts" de votre côté (au niveau de l'application).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X