MongoDB 数据建模
一、基本原则:
优先内嵌,其次引用 ---- 主子压缩成1个表
1:1、 1:n 强关联聚合(主子) 子数量不是特别多时直接用内嵌文档
m:n 使用reference ,关联表, 更新等要保证事务性
二、模型例子
1、电商建模: https://blog.csdn.net/wanght89/article/details/77197400
product和分类
{
slug:"wheel-barrow-9092",
sku:"9092",
name:"Extra Large Wheel Barrow",
description:"Heavy duty wheel barrow",
details:{
weight:47,
weight_unite:"1bs",
model_num:40392882,
manufacturer:"Acme",
color:"Green"
},
total_review:4,
average_review:4.5,
pricing:
{
retail:589700,
sale:489700
},
price_history:[
{
retail:529700,
sale:429700,
start:new Date(2010,4,1),
end:new Date(2010,4,8)
},
{
retail:529700,
sale:529700,
start:new Date(2010,4,9),
end:new Date(2010,4,16)
}
],
cateory_ids:[
new ObjectId("59884ee3b53fab2a8024b6ae"),
new ObjectId("59884ee3b53fab2a8024b6af")
],
main_cate_id:new ObjectId("59884ee3b53fab2a8024b6b1"),
tags:["tools","gardening","soil"]
}
order 订单
{
_id:new ObjectId("6a5b1476238d3b4dd5000001"),
user_id:new ObjectId("4a5b1476238d3b4dd5000001"),
state:"CART",
line_items:[{
_id:new ObjectId("4a5b1472134d3b4dd5000921"),
sku:"9092",
name:"Extra Large Wheel Barrow",
quantity:1,
pricing:{
retail:5897,
sale:4897,
}
},
{
_id:new ObjectId("4a5b1472134d3b4dd5000922"),
sku:"10027",
name:"Rubberized Work Glove,Block",
quantity:2,
pricing:{
retail:1499,
sale:1299,
}
}
],
shipping_address:{
street:"588 5th Street",
city:"Brooklyn",
state:"NY",
zip:11215
},
sub_total:6196
}
用户
{
_id:new ObjectId("4a5b1476238d3b4dd5000001"),
email:"kylebanker@gl.com",
first_name:"Kyle",
last_name:"Banker",
hashed_password:"bd1cfa194c3a603e7186780824b04419",
address:[
{ name:"home",
street:"588 5th Street",
city:"Brooklyn",
state:"NY",
zip:10010
},
{
name:"work",
street:"1 E.23rd Street",
city:"New York",
state:"NY",
zip:10010
}
],
payment_methods:[{
name:"VISA",
last_four:2127,
crypted:"43f6baldfda6b8106dc7",
expiration_date:new Date(2014,4)
}
]
}
评论
{
_id:new ObjectId("4c4b1476238d3b4dd5000041"),
product_id:new ObjectId("59884b76b53fab2a8024b6ad"),
date:new Date(2010,5,7),
title:"Amazing",
text:"Has a squeaky wheel,but still a darn good wheel barrow",
rating:4,
user_id:new ObjectId("4a5b1476238d3b4dd5000001"),
user_name:"dgreenthumb",
helpful_votes:3,
voter_ids:[
new ObjectId("59884b76b53fab2a8024b600"),
new ObjectId("59884b76b53fab2a8024b601"),
new ObjectId("59884b76b53fab2a8024b602")
}
}
购物车 = items
2、博客:https://www.qikegu.com/docs/3277
1>user
2>article= comments+ tags + categorys + user
3、社交
关注: m:n 都比较大时,使用单独的关联表
朋友圈: 每个人存储1份url 使用bucket可以控制数组的大小
iot数据采集:可以采用分桶的方式提高性能(每一个小时的聚合到一个文档里,并做好聚合) 异构的优势
4、电影统计
actor
movie = reviews + 。。。
三、书籍和资料
https://www.lagou.com/lgeduarticle/28746.html
设计模式范式
https://cloud.tencent.com/developer/article/1405900
A Complete Methodology of Data Modeling for MongoDB
Advanced Schema Design Patterns, Daniel Coupal
<MongoDB应用设计模式>
四、常见问题,建模范式(访问模式需求,决定架构设计)
1、多态 每个document字段都不同,
适合场景:单一视图、内容管理、移动应用、产品目录
2、属性模式(Attribute Pattern)-- 把固定的列,变成kv的动态列
UserDefinedField https://martinfowler.com/bliki/UserDefinedField.html
动态属性子表或者固定的冗余列(分散到每个单据,集中有个配置的地方)
问题:部分文档有公共的属性,或者只关注部分属性
电影在多个国家有多个发行日期,怎么查询发行日期?
方案:统一到1个数组字段,里面obj是kv的结构
{
title: "Star Wars",
director: "George Lucas",
...
release_US: ISODate("1977-05-20T01:00:00+01:00"),
release_France: ISODate("1977-10-19T01:00:00+01:00"),
release_Italy: ISODate("1977-10-20T01:00:00+01:00"),
release_UK: ISODate("1977-12-27T01:00:00+01:00"),
...
}
{
title: "Star Wars",
director: "George Lucas",
...
releases: [
{
location: "USA",
date: ISODate("1977-05-20T01:00:00+01:00")
},
{
location: "France",
date: ISODate("1977-10-19T01:00:00+01:00")
},
{
location: "Italy",
date: ISODate("1977-10-20T01:00:00+01:00")
},
{
location: "UK",
date: ISODate("1977-12-27T01:00:00+01:00")
},
...
],
...
}
索引:{ "releases.location": 1, "releases.date": 1}
"specs": [
{ k: "volume", v: "500", u: "ml" },
{ k: "volume", v: "12", u: "ounces" }
]
{"specks.k": 1, "specs.v": 1, "specs.u": 1}
3、桶模式 定时分组+预先统计,减少索引带来的内存消耗
{
sensor_id: 12345,
timestamp: ISODate("2019-01-31T10:00:00.000Z"),
temperature: 40
}
{
sensor_id: 12345,
timestamp: ISODate("2019-01-31T10:01:00.000Z"),
temperature: 40
}
{
sensor_id: 12345,
timestamp: ISODate("2019-01-31T10:02:00.000Z"),
temperature: 41
}
{
sensor_id: 12345,
// 每个小时统计1次
start_date: ISODate("2019-01-31T10:00:00.000Z"),
end_date: ISODate("2019-01-31T10:59:59.000Z"),
measurements: [
{
timestamp: ISODate("2019-01-31T10:00:00.000Z"),
temperature: 40
},
{
timestamp: ISODate("2019-01-31T10:01:00.000Z"),
temperature: 40
},
...
{
timestamp: ISODate("2019-01-31T10:42:00.000Z"),
temperature: 42
}
],
transaction_count: 42,
sum_temperature: 2413
}
4、例外模式(Outlier)
问题:突然增长很多数据,比如:影评、书籍畅销榜、社交好友关系
添加个 "has_extras": "true",标记是否有非常多的数组元素,有的话去外部关联
{
"_id": ObjectID("507f191e810c19729de860ea"),
"title": "Harry Potter, the Next Chapter",
"author": "J.K. Rowling",
...,
"customers_purchased": ["user00", "user01", "user02", ..., "user999"],
"has_extras": "true"
}
5、计算模式 Computed Pattern
问题:
总收入、观看人数等聚合运算非常耗费性能,可以在后台计算。
方案:
每个子项目插入或更新时直接计算汇总的结果,同时记录时间戳表示上次更新的时间,适合写少读多
例子:iot时序数据、产品分类、大屏应用(single view applications)
6、The Subset Pattern 缩减内存使用
内存缓存提高性能,但是内存不足时怎么办? 加内存、做shard分片
场景:商品的评论,电影的演员 (大量非热点数据不应该放入内存)
方案:把全部存储到product,变成product存储热数据,comment存储历史数据 (需要join一次)
7、Extended Reference Pattern
场景:需要join多个表,来表达非热点数据
方案:不是纯粹的外键关联,而是把常用的字段直接关联复制进来
缺点:数据重复
8、近似模式 The Approximation Pattern
场景:不需要非常准确(具有统计意义就可以),但是需要足够快。比如一个城市的常驻人口数量。
方案:不是每行数据都进行更新,每100行,或每一段时间更新一次
9、The Tree Pattern 树形结构
关系模型:parent_id 或children(list)
MongoDB:后代同时维护 ancestors:[]和 parent
10、 Preallocation Pattern 预分配
使所有数据的数据结构是一致的,哪怕初始的时候是空的,后面再去填充
例子:电影院/酒店的每日订阅情况,4月的工作日有哪些(结构一致会使得算法简单了很多)
11、Document Versioning Pattern 文档版本 ---- 添加version字段
不仅是读最新数据,也需要读历史的版本信息。
前提:版本个数不多,需要多版本的文档也不多,大部分还是使用最新版本的数据
适合于强监管的行业,比如金融、医疗、法律、保险
场景:保险主体和附属条款
current:
{
version:19,
items:[]
}
history: 所有的历史版本
{
version:1,
items:[]
},
{
version:2,
items:[]
},
简单说:每次修改后,生成新版本,把老版本那一行拷贝到历史库。需要使用历史数据时,从历史库里进行查询
12、The Schema Versioning Pattern 结构多版本
添加 schema_version 字段,表示新的数据库模式,可以实现不强制升迁数据库的情况下,升级程序。或者同时有多个版本的存储结构
customer
{
"_id": "<ObjectId>",
"name": "Anakin Skywalker",
"home": "503-555-0000",
"work": "503-555-0010"
}
{
"_id": "<ObjectId>",
"schema_version": "2",
"name": "Anakin Skywalker (Retired)",
"contact_method": [
{ "work": "503-555-0210" },
{ "mobile": "503-555-0220" },
{ "twitter": "@anakinskywalker" },
{ "skype": "AlwaysWithYou" }
]
}
五、其他
https://blog.csdn.net/Real_Myth/article/details/51781099
设计模式策略
1、节点读写分离
2、事务
db.queue.insert( { _id : 123,
message : { },
locked : false,
tlocked : ISODate(),
try : 0 });
var timerange = date.Now() - TIMECONSTANT;
var doc = db.queue.findAndModify( { $or : [ { locked : false }, { locked : true, tlocked : {
$lt : timerange } } ], { $set : { locked : true, tlocked : date.Now(), $inc : { try : 1 } } }
);
//do some processing
db.queue.update( { _id : 123, try : doc.try }, { } );
3、path存储全路径
4、用嵌套避免join
https://mongoing.com/mongodb-advanced-pattern-design
文档最大16M。一个数组太大会严重影响性能
方法论:
数据量
场景
模型:做合适的内嵌
设计模式识别
树形结构:
1、关联 parent
2、存储children数组
3、关联 parent 和所有祖先
4、带有 编码结构的path
钱和时间的数据类型 https://docs.mongodb.com/manual/tutorial/model-time-data/
数据模型需要处理的问题:
实现 泛化
关联 1、聚合; 参照 2、组合; 主子
相关推荐
总结来说,"JavaScript_MongoDB对象建模设计在异步环境中工作"的主题涵盖了JavaScript异步编程、MongoDB对象建模以及Mongoose库的使用。通过Mongoose,开发者可以方便地在JavaScript异步环境中与MongoDB进行交互,...
1. **数据建模**:合理设计数据模型对于提升MongoDB的性能至关重要。应根据实际应用场景选择合适的数据结构,如嵌入式文档、引用文档等。 2. **索引策略**:正确使用索引可以显著提高查询效率。需要根据查询模式来...
- 金融数据中台的参考架构展示了一个集成了多种数据来源、处理和分析功能的复杂系统,包括数据治理、同步、建模、去重、API集成等。 5. 数据中台的主要价值: - 数据协同:提高不同部门间数据的协作效率。 - ...
数据建模是IT行业中至关重要的一个环节,尤其是在数据库设计阶段,它可以帮助我们清晰地定义、组织和理解数据的结构和关系。"很实用的数据建模文档"无疑为初学者提供了一个宝贵的资源,帮助他们掌握这一关键技能。在...
RDBMS到MongoDB迁移白皮书 -涵盖了将数据从RDBMS移至MongoDB时的最佳实践和注意事项 MongoDB现代化记分卡 -使用它来确定哪些现有的旧版...完整的数据建模方法 -此演示文稿将指导您完成MongoDB支持的多种数据模型
问答 API入门要让 Node 服务器在本地运行: 克隆这个 repo npm install安装所有必需的依赖项创建 MongoDb 集群并获取连接 MongoDb URI 在./config/env下的config.env设置环境...JWT - 用于将 MongoDB 数据建模和映射
12. **应用程序设计**:指导如何设计适合 MongoDB 的应用程序架构,包括数据建模的最佳实践和分片策略。 通过深入阅读并理解"复件 MongoDB Manual",无论是开发人员还是数据库管理员,都能掌握 MongoDB 的核心功能...
数据建模是定义数据结构的过程,它决定了数据在 MongoDB 中的组织形式。有效的数据建模可以显著提高数据库性能和可维护性。 **4.2 文档验证** MongoDB 支持对文档进行模式验证,可以通过 JSON Schema 来指定文档的...
Mongoose是一个MongoDB对象建模工具,旨在满足对建模应用程序数据的更好方法的需求。 它旨在在异步环境中工作,提供了一种简单,直接的对象建模方法,从而跳过了编写MongoDB验证,转换和业务逻辑样板的繁琐任务。 ...
用于将MongoDB数据建模和映射到javascript -node.js的HTTP请求记录器中间件 status-与HTTP状态代码进行交互的实用程序。 对象模式描述语言和JavaScript对象的验证器。 -CORS是一个node.js程序包,用于提供可用于...
本书内容涉及多种设计模式,其中包括数据嵌入(Embedding)与数据引用(Referencing)的权衡,这是设计MongoDB数据模型时经常需要考虑的问题。在关系型数据库中,数据模型通常通过规范化来优化,而在MongoDB这样的...
在数据建模方面,我们学习了MongoDB的规范化模型和非规范化模型,并探索了MongoDB的查询方法,包括读操作、查询操作符以及数组查询等。 然后,内容转向Pentaho的入门,详细说明了如何安装Pentaho以及如何通过...
2. **数据建模**:MongoDB的设计与传统关系型数据库有所不同,书中深入探讨了如何进行非关系型数据建模,包括分片、引用和嵌入式数据模型的设计原则,帮助开发者理解如何根据业务需求选择合适的数据结构。...
总体而言,MongoDB架构指南为我们提供了一套完整的关于MongoDB设计、建模、查询和管理的知识体系。这些内容对于希望在现代应用中使用MongoDB的开发人员和管理员来说都是宝贵的资源。无论是在构建大规模、高可用性的...
11. **图形化数据建模**:Compass的图形化数据建模工具帮助用户理解数据之间的关系,可以创建和验证数据模式,有助于优化数据存储和查询。 12. **云集成**:对于使用MongoDB Atlas(MongoDB的云服务)的用户,...
3. **数据分析与报表设计**: Chapter 4可能深入到了数据分析部分,使用Pentaho Report Designer创建基于MongoDB数据的报表和仪表板。这可能涵盖如何设计和布局报表、使用聚合函数、应用过滤条件、以及创建图表和图形...
这是一个图形用户界面工具,可以帮助用户直观地查看和管理数据库,执行查询,分析数据分布,甚至进行简单的数据建模。此外,还有像Robo 3T这样的第三方工具,提供了更高级的功能,如SSH隧道连接、脚本编辑等。 在...
在MongoDB 3.0版本中,Compass可能已经支持了更多高级功能,如聚合框架的可视化操作、数据建模等。 Robo 3T则是一款轻量级的MongoDB管理工具,它提供了类似于SQL的查询界面,适合开发者和DBA使用。在3.0版本后,...
数据模型介绍部分会涉及到数据建模的概念、原则以及一些常见的数据建模案例和模式,数据模型参考部分则是对数据模型中常见元素的深入分析和使用建议。 在数据库的管理方面,MongoDB提供了丰富的管理工具和方法。在...
"MongDB数据库操作和面试专题及答案"是一份涵盖MongoDB数据库操作技术和面试准备内容的资源,旨在帮助学习者深入理解MongoDB...5. **数据建模**:了解MongoDB的数据建模方法,包括文档设计、嵌入式文档、引用等技术。