Внешние ключи в монго? - PullRequest
76 голосов
/ 13 июня 2011

enter image description here

Как мне разработать такую ​​схему в MongoDB?Я думаю, что нет внешних ключей!

Ответы [ 4 ]

58 голосов
/ 13 июня 2011

Как спроектировать таблицу в mongodb?

Во-первых, проясним некоторые соглашения об именах. MongoDB использует collections вместо tables.

Я думаю, что нет внешних ключей!

Возьмите следующую модель:

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

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

Очевидно, что список курсов Джейн указывает на некоторые конкретные курсы. База данных не налагает никаких ограничений на систему (, то есть: ограничения внешнего ключа ), поэтому нет «каскадного удаления» или «каскадного обновления». Тем не менее, база данных содержит правильную информацию.

Кроме того, MongoDB имеет стандарт DBRef , который помогает стандартизировать создание этих ссылок. Фактически, если вы посмотрите на эту ссылку, у нее будет похожий пример.

Как я могу решить эту задачу?

Для ясности, MongoDB не является реляционным. Стандартной «нормальной формы» не существует. Вам следует смоделировать базу данных в соответствии с данными, которые вы храните, и запросами, которые вы намерены выполнять.

21 голосов
/ 13 июня 2011

Вас может заинтересовать использование ORM, например, Mongoid или MongoMapper.

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

В базе данных NoSQL, такой как MongoDB, есть не «таблицы», а документы. Документы сгруппированы внутри Коллекции. Вы можете иметь любой вид документа - с любым видом данных - в одной коллекции. По сути, в базе данных NoSQL вам решать, как организовать данные и их отношения, если они есть.

Что делают Mongoid и MongoMapper, так это предоставляют вам удобные методы для установки отношений довольно легко. Проверьте ссылку, которую я дал вам, и спросите любую вещь.

Edit:

В монгоиде вы напишите свою схему так:

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

Вы можете использовать этот ObjectId для связи между документами.

14 голосов
/ 05 сентября 2013

С Маленькая книга MongoDB

Еще одна альтернатива использованию объединений - денормализация ваших данных. Исторически денормализация была зарезервирована для чувствительный к производительности код, или когда данные должны быть сняты (как в журнале аудита). Тем не менее, с растущая популярность NoSQL, многие из которых не имеют соединений, денормализация как часть нормального моделирования становится чаще. Это не означает, что вы должны дублировать каждый фрагмент информации в каждом документе. Тем не мение, вместо того, чтобы бояться дублирования данных управлять вашими проектными решениями, рассмотрите возможность моделирования ваших данных на основе того, что к какому документу относится информация.

Итак,

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

Если это данные API RESTful, замените идентификатор курса ссылкой GET на ресурс курса

13 голосов
/ 08 мая 2017

Мы можем определить так называемый foreign key в MongoDB. Однако нам необходимо поддерживать целостность данных НА СЕБЯ . Например,

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

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

Поле courses содержит _id с курсов. Легко определить отношение один ко многим. Однако, если мы хотим получить имена курсов студента Jane, нам нужно выполнить еще одну операцию для получения документа course через _id.

Если курс bio101 удален, нам нужно выполнить еще одну операцию для обновления поля courses в документе student.

Подробнее: Разработка схемы MongoDB

Тип документа MongoDB поддерживает гибкие способы определения отношений. Чтобы определить отношение «один ко многим»:

Встроенный документ

  1. Подходит для одного-немногим.
  2. Преимущество: нет необходимости выполнять дополнительные запросы к другому документу.
  3. Недостаток: невозможно управлять сущностью встроенных документов по отдельности.

Пример:

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

Ссылка на ребенка

Как и в примере student / course.

Ссылка на родителя

Подходит для от одного до нескольких миллиардов, например для сообщений журнала.

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
}

Фактически, host является родителем logmsg. Ссылка на идентификатор host экономит много места, учитывая, что сообщения журнала составляют миллиарды.

Ссылки:

  1. 6 Практических правил для схемы схемы MongoDB: Часть 1
  2. 6 Практических правил для схемы схемы MongoDB: Часть 2
  3. 6 Практических правил для схемы схемы MongoDB: Часть 3
  4. Типовые отношения «один ко многим» со ссылками на документы
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...