在mongo的外键?

Mar*_*sov 81 sql foreign-keys mongodb nosql

在此输入图像描述

如何在MongoDB中设计这样的方案?我觉得没有外键!

Gat*_* VP 61

如何在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'
}
Run Code Online (Sandbox Code Playgroud)

显然,Jane的课程列表指向一些特定的课程.数据库不对系统应用任何约束(即:外键约束),因此没有"级联删除"或"级联更新".但是,数据库确实包含正确的信息.

此外,MongoDB有一个DBRef标准,可帮助标准化这些引用的创建.事实上,如果你看看那个链接,它有一个类似的例子.

我该如何解决这个任务?

要明确的是,MongoDB不是关系型的.没有标准的"正常形式".您应该根据您存储的数据和要运行的查询对数据库建模.

  • 好的,但我如何从学生收藏中获取源名称数据?db.student.find()将返回类似课程的内容:[{course:'bio101',mark:85}] (2认同)

Ner*_*ian 25

您可能有兴趣使用像Mongoid或MongoMapper这样的ORM.

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

在像MongoDB这样的NoSQL数据库中,没有"表"而是文档.文档在集合中分组.您可以在一个集合中包含任何类型的文档 - 包含任何类型的数据.基本上,在NoSQL数据库中,由您来决定如何组织数据及其关系(如果有的话).

Mongoid和MongoMapper的作用是为您提供方便的方法来轻松建立关系.查看我给你的链接并询问任何事情.

编辑:

在mongoid你会写这样的计划:

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
Run Code Online (Sandbox Code Playgroud)

编辑:

> 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" }
Run Code Online (Sandbox Code Playgroud)

您可以使用该ObjectId来执行文档之间的关系.

  • 对于以后的读者来说,“表”是MongoDB中的“集合”。行是文档,列是字段...以防万一您混淆了。 (2认同)

ZAk*_*Aky 15

来自The Little MongoDB Book

使用连接的另一种替代方法是对数据进行非规范化.从历史上看,非规范化是为性能敏感的代码保留的,或者是应该对数据进行快照(如在审计日志中).然而,随着NoSQL的日益普及,其中许多没有连接,非规范化作为正常建模的一部分变得越来越普遍.这并不意味着您应该复制每个文档中的每条信息.但是,不要让对重复数据的恐惧驱动您的设计决策,而应考虑根据哪些信息属于哪个文档来建模数据.

所以,

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

如果是RESTful API数据,请将课程ID替换为课程资源的GET链接


Joy*_*Joy 15

我们可以foreign key在MongoDB中定义所谓的.但是,我们需要保持数据完整性BY OURSELVES.例如,

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

course
{
  _id: 'bio101',
  name: 'Biology 101',
  description: 'Introduction to biology'
}
Run Code Online (Sandbox Code Playgroud)

courses字段包含_ids课程.定义一对多关系很容易.但是,如果我们想要检索学生的课程名称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' }
  ]
}
Run Code Online (Sandbox Code Playgroud)

儿童参考

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
}
Run Code Online (Sandbox Code Playgroud)

实际上,a host是a 的父级logmsg.引用hostid会节省很多空间,因为日志消息是squillions.

参考文献:

  1. MongoDB架构设计的6个经验法则:第1部分
  2. 3 MongoDB架构设计的经验法则:第2部分
  3. 3 MongoDB架构设计的经验法则:第3部分
  4. 与文档参考的模型一对多关系