Foreign keys in mongo?

enter image description here

How do I design a scheme such this in MongoDB? I think there are no foreign keys!

163738 次浏览

您可能对使用诸如 Mongoid 或 MongoMapper 之类的 ORM 感兴趣。

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

在像 MongoDB 这样的 NoSQL 数据库中,不存在“表”,而是集合。文档在集合中分组。您可以在单个集合中拥有任何类型的文档(包含任何类型的数据)。基本上,在 NoSQL 数据库中,决定如何组织数据及其关系(如果有的话)取决于您。

Mongoid 和 MongoMapper 所做的就是为您提供方便的方法来非常容易地建立关系。看看我给你的链接,随便问点什么。

编辑:

用蒙古语写下你的计划:

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

如何设计这样的表在蒙戈德布?

首先,澄清一些命名约定。 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 标准,可以帮助标准化这些引用的创建。事实上,如果你看看这个链接,它有一个类似的例子。

我怎样才能解决这个问题?

需要说明的是,MongoDB 不是关系型的。没有标准的“规范形式”。您应该根据所存储的数据和打算运行的查询对数据库进行建模。

来自 小 MongoDB 书

使用连接的另一种替代方法是将数据反规范化 性能敏感的代码,或者应该对数据进行快照处理(如审计日志) NoSQL 越来越受欢迎,其中许多没有连接,作为正常建模的一部分的反规范化正在成为 这并不意味着你应该复制每个文档中的每一条信息, 与其让对重复数据的恐惧驱动您的设计决策,不如考虑根据什么来建模您的数据 信息属于什么文件。

那么,

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

如果它是一个 RESTful API 数据,则将课程 ID 替换为指向课程资源的 GET 链接

我们可以在 MongoDB 中定义所谓的 foreign key,但是,我们需要维护数据完整性 我们自己,

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


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

字段包含课程的 _id

如果课程 bio101被删除,我们需要执行另一个操作来更新 student文档中的 courses字段。

更多: 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
}

实际上,hostlogmsg的父母。引用 host id 可以节省很多空间,因为日志消息非常多。

参考文献:

  1. MongoDB 模式设计的6条经验法则: 第1部分
  2. MongoDB 模式设计的6条经验法则: 第2部分
  3. MongoDB 模式设计的6条经验法则: 第3部分
  4. 具有文档引用的模型一对多关系

ForeignKey 的用途是防止在字段值与其 ForeignKey 不匹配时创建数据。为了在 MongoDB 中实现这一点,我们使用 Schema 中间件来确保数据的一致性。

请看一下文件。 Https://mongoosejs.com/docs/middleware.html#pre

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

引用通过包含链接或 从一个文档到另一个文档的引用。应用程序可以解析 访问相关数据的引用 规范化数据模型。

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

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

我认为没有理由不能使用 NOSQL 数据库作为关系数据库,因为您拥有聚合管道,可以用来创建类似 SQL 内部连接的视图。

每个集合应该包含一个类型,例如: order 和 order-Details 是1: M 关系。

订单收集
Id (PK)类型: GUID
OrderNo (候选或备选 PK)
订购日期
顾客(FK)
... 更多的命令字段 < br >

收集订单细节
身份证(PK)
有序(FK)
产品(FK)
数量
... 更多字段 < br >

产品
身份证(PK)
Supplierid (FK)
姓名
成本 < br >

诸如此类。

之所以不简单地使用关系数据库,是因为 NOSQL 数据库还有其他特性,可以与关系设计的数据集合一起使用。

实现关系的方法与关系数据库中的方法相同。您必须自己添加外键(为每个文档对象自动添加主键)并创建规范化的连接集合。数据库通常不会自我标准化。

唯一需要注意的是,你必须自己编写参照完整性,因为 NOSQL 还没有这么做。因此,在您的管理 UI 中,如果用户试图删除有子女的父亲,您会抛出一个友好的错误,说他们必须首先删除子女。这并不困难,但是在使用 DB 实用程序时仍然需要小心,不要删除有子元素的父元素,因为 DB 允许这样做。

始终使用外键 id 的命名约定。例如:

订单-细节收集
身份证(PK)
秩序(FK)。通过坚持这个变数命名原则,您可以很容易地推断出这个外键是 Order 集合中的主键。