NoSQL记录建模与更新方法:传统关系型表结构如何映射到Dynamodb等NoSQL数据库
NoSQL 针对用户-公司场景的建模方案
1. MongoDB 建模思路
根据业务读写频率可以选择两种方案:
方案一:嵌入式冗余设计(适合读多写少场景)
如果业务查询用户信息时,90%以上的场景都需要带出所属公司信息,可以直接把公司的核心字段冗余到用户文档中,用户文档示例:
{ "_id": ObjectId("xxx"), "username": "j23", "company_id": ObjectId("yyy"), "company": { "name": "A Really boring company", "owner_id": ObjectId("xxx") }, "email": "something@gmail.com", "is_company_owner": true }
同时单独保留公司集合作为公司核心属性的唯一可信数据源,公司文档示例:
{ "_id": ObjectId("yyy"), "owner_id": ObjectId("xxx"), "name": "A Really boring company" }
公司名称更新处理:
- 先更新公司集合中对应记录的名称,保证核心数据源准确
- 再执行批量更新语句修改所有关联该
company_id的用户文档冗余字段:db.users.updateMany( { "company_id": ObjectId("yyy") }, { $set: { "company.name": "New Company Name" } } )
如果公司名称更新频率极低(比如数月才修改一次),这种方案的读性能最优,批量更新的开销可以忽略。
方案二:引用式关联设计(适合写多读少场景)
如果公司信息更新非常频繁,就只在用户文档中存储company_id,查询用户时用$lookup做关联查询即可,不需要冗余公司字段。这种方案下更新公司名称只需要修改公司集合的单条记录,缺点是查询用户信息时会多一次关联开销。
2. DynamoDB 建模思路
DynamoDB属于键值/文档型数据库,优先按照实际访问模式设计表结构,推荐用单表设计:
| PK(分区键) | SK(排序键) | username | company_name | owner_id | |
|---|---|---|---|---|---|
| USER#1 | METADATA | j23 | something@gmail.com | A Really boring company | 1 |
| USER#2 | METADATA | fj222 | james@aol.com | A Really boring company | 1 |
| COMPANY#1 | METADATA | A Really boring company | 1 |
公司名称更新处理:
- 先更新
PK=COMPANY#1的单条记录的公司名称 - 小规模用户量可以直接用PartiQL语句批量更新所有关联用户记录:
UPDATE "表名" SET company_name = 'New Company Name' WHERE PK BEGINs WITH 'USER#' AND owner_id = 1
如果用户量极大,也可以搭配DynamoDB Stream触发异步批量更新,不用同步等待所有用户记录更新完成,避免请求超时。
内容的提问来源于stack exchange,提问作者dataviews
相关产品推荐
相关产品推荐

