MongoDB 学习笔记 - Data Models
Data Model概念
如果要给MongoDB打标签,那么首选的几个标签无非是NoSQL, 非关系型数据库, 分布式文档存储数据库。而关系型数据库,非关系型数据库一个非常重要的区别就是Data Model。Data Model 决定了“要怎么存”,“适用怎么查”等,也是选型的一个重要考虑因素。
所以呐,我们不能用MySQL那一套建表的惯性来思考。MongoDB的Data Model主要有两类,Embedded Data Models和Normalized Data Models。
Embedded Data Models
嵌入式数据模型,顾名思义,我们把子文档嵌入在主文档里面。如下图,主文档是用户属性,而用户的联系方式,操作权限级别等子属性,一并用嵌入的方式,放进我们的用户属性文档里面。
这种数据模型可以很好的应用于“一对一”,“一对多”的关系结构上,例如上面的用户联系方式就是“一对一”,用户操作权限级别就是“一对多”(一个用户只有一个操作级别,一个操作级别对应很多用户)。
?? 优势:??MongoDB本身是推荐使用这样的数据模型的。其一,因为这种结构对于“读”场景来说,只用做一次读操作,不用去查很多表;其二,MongoDB对单文档操作时原子性的,所以天生对于一个文档的不同field的更新操作是安全的。
?? 缺点:数据冗余,以及数据冗余带来的性能问题等;“多对多”的关系比较难以表达。
Normalized Data Model
标准化数据模型,就和之前学过的关系型数据库很像了,它使用references来关联两个文档。
标准化数据模型主要就是针对嵌入式数据模型的两个缺点来补充的。而对于标准化数据模型查询时,避免不了的join操作,MongoDB提供了$lookup,$graphLookup来提供。但是我们在使用MongoDB的时候,仍然需要优先考虑嵌入式数据模型。如果必须存在很多join操作,那需要考虑是不是不要使用MongoDB了。
设计Data Model
官方讲座
数据模型的应用场景
这里列举一些官方展示的应用场景的考虑:
原子操作
如果有些field需要作为一个原子操作一起更新,就需要考虑把它们放在一个文档里面。例如图书馆里书籍信息里面的可用数量和借书信息需要一起更新:
{
_id: 123456789,
title: "MongoDB: The Definitive Guide",
author: [ "Kristina Chodorow", "Mike Dirolf" ],
published_date: ISODate("2010-09-24"),
pages: 216,
language: "English",
publisher_id: "oreilly",
available: 3,
checkout: [ { by: "joe", date: ISODate("2012-10-15") } ]
}
就可以:
db.books.updateOne (
{ _id: 123456789, available: { $gt: 0 } },
{
$inc: { available: -1 },
$push: { checkout: { by: "abc", date: new Date() } }
}
)
关键字搜索
这里的关键字搜索和全文搜索是不一样的。MongoDB可以创建multi-key index。图书管理书籍信息如下:
{ title : "Moby-Dick" ,
author : "Herman Melville" ,
published : 1851 ,
ISBN : 0451526996 ,
topics : [ "whaling" , "allegory" , "revenge" , "American" ,
"novel" , "nautical" , "voyage" , "Cape Cod" ]
}
可以在topics数组上创建multi-key index
db.volumes.createIndex( { topics: 1 } )
查询就可以根据关键字查,如:
db.volumes.findOne( { topics : "voyage" }, { title: 1 } )
其他
例如针对金融数据,IoT数据等等