在mongo的外键?

时间:2011-06-13 17:40:35

标签: sql mongodb foreign-keys nosql

enter image description here

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

6 个答案:

答案 0 :(得分:57)

  

如何在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'
}

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

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

  

我该如何解决这个问题?

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

答案 1 :(得分:21)

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

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

在像MongoDB这样的NoSQL数据库中,没有'tables'而是文档。文档在集合中分组。您可以在一个集合中包含任何类型的文档 - 包含任何类型的数据。基本上,在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

编辑:

> 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来处理文档之间的关系。

答案 2 :(得分:14)

来自The Little MongoDB Book

  

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

所以,

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

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

答案 3 :(得分:12)

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

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. 缺点:无法单独管理嵌入文档的实体。
  4. 示例:

    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
    }
    

    实际上,hostlogmsg的父级。引用host id可以节省大量空间,因为日志消息是非常广泛的。

    参考文献:

    1. 6 Rules of Thumb for MongoDB Schema Design: Part 1
    2. 6 Rules of Thumb for MongoDB Schema Design: Part 2
    3. 6 Rules of Thumb for MongoDB Schema Design: Part 3
    4. Model One-to-Many Relationships with Document References

答案 4 :(得分:1)

简答: 您应该使用 ObjectId 属性在集合之间使用“弱引用”:

<块引用>

引用通过包含链接或 从一个文档到另一个文档的引用。应用程序可以解决 这些引用访问相关数据。大体上,这些是 标准化数据模型。

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

这当然不会检查任何参照完整性。您需要在您这边(应用程序级别)处理“死链接”。

答案 5 :(得分:0)

ForeignKey的目的是在字段值与其ForeignKey不匹配时阻止创建数据。为了在MongoDB中完成此任务,我们使用Schema中间件来确保数据的一致性。

请查看文档。 https://mongoosejs.com/docs/middleware.html#pre