|
|
|
@ -331,4 +331,122 @@ data: xxxx
|
|
|
|
|
|
|
|
|
|
### 4. 设计模式集锦
|
|
|
|
|
|
|
|
|
|
- 问题: 大文档, 很多字段, 很多索引
|
|
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
title: "Dunkirk",
|
|
|
|
|
release USA:"2017/07/23",
|
|
|
|
|
release UK:"2017/08/01",
|
|
|
|
|
release France:"2017/08/01",
|
|
|
|
|
release Festival San Jose:"2017/07/22"
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
- 需要很多索引
|
|
|
|
|
```json
|
|
|
|
|
{release_UsA:1}
|
|
|
|
|
{release_UK:1}
|
|
|
|
|
{release_France:1}
|
|
|
|
|
{release_Festival_San_Jose:1 }
|
|
|
|
|
```
|
|
|
|
|
- 电影的上映时间
|
|
|
|
|
|
|
|
|
|
- 解决方法: 列转行
|
|
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
title: "Dunkirk",
|
|
|
|
|
releases:[
|
|
|
|
|
{country:"USA",date:"2017/7/23"},
|
|
|
|
|
{country:"Uk",date:"2017/08/01”}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
- 转换后: 字段数变少了
|
|
|
|
|
- 创建索引: db.movies.createIndex({"releases.country":1, "releases.date":1})
|
|
|
|
|
|
|
|
|
|
- 模式小结:
|
|
|
|
|
- 场景: 产品属性多, 多语言(多国家属性)
|
|
|
|
|
- 痛点: 文档中有很多类似的字段, 会用于组合查询搜索, 需要创建很多索引
|
|
|
|
|
- 设计模式方案及优点: 转化为数组, 一个索引解决所有查询问题
|
|
|
|
|
|
|
|
|
|
- 问题: 模型灵活了, 如何管理文档的不同版本
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
"id":ObiectId("5de26f197edd62c5d388babb"),
|
|
|
|
|
"name":"TJ",
|
|
|
|
|
"Tapdata""company":
|
|
|
|
|
```
|
|
|
|
|
- v1.0
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
"id":obiectId("5de26f197edd62c5d388babb")
|
|
|
|
|
"name":"TJ"
|
|
|
|
|
"company":"Tapdata"
|
|
|
|
|
"wechat":"titang826"
|
|
|
|
|
"schema_version": "2.0"
|
|
|
|
|
```
|
|
|
|
|
- v2.0
|
|
|
|
|
- 解决方案:schema_version 使用这个字段进行区分标识
|
|
|
|
|
|
|
|
|
|
- 模式小结:版本字段
|
|
|
|
|
- 场景: 任何有版本衍生的数据库
|
|
|
|
|
- 痛点: 文档模型格式多, 无法知道其合理性, 升级时候需要更新太多文档
|
|
|
|
|
- 设计模式及优点: 增加一个版本号字段, 快速过滤掉不需要升级的文档, 升级时候对不同的文档做不同的升级
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- 问题: 统计网页点击流量
|
|
|
|
|
- 每访问一个页面就会产生一次数据库计数更新操作
|
|
|
|
|
- 统计数字准确性并不十分重要
|
|
|
|
|
|
|
|
|
|
- 解决方案: 用近似计算
|
|
|
|
|
- 每隔 10(X)次写一次
|
|
|
|
|
- Increment by 10(X)
|
|
|
|
|
- {$inc:{views:1}}
|
|
|
|
|
- if random(0,9) == 0 increment by 10
|
|
|
|
|
|
|
|
|
|
- 模式小结: 近似计算
|
|
|
|
|
- 场景:
|
|
|
|
|
- 网页计数
|
|
|
|
|
- 各种结果不需要准确的排名
|
|
|
|
|
- 痛点:
|
|
|
|
|
- 写入太频繁, 消耗系统资源
|
|
|
|
|
- 设计模式方案及优点
|
|
|
|
|
- 间隔写入, 每隔10次或者100次
|
|
|
|
|
- 大量减少写入需求
|
|
|
|
|
|
|
|
|
|
- 问题: 业绩排名, 游戏排名, 商品统计等精确统计
|
|
|
|
|
- 热销榜: 某个商品今天卖了多少, 这个星期卖了多少, 这个月卖了多少?
|
|
|
|
|
- 电影排行: 观影者, 场次统计
|
|
|
|
|
- 传统解决方案: 通过聚合计算
|
|
|
|
|
- 痛点: 消耗资源多, 聚合计算时间长
|
|
|
|
|
|
|
|
|
|
- 解决方案: 用预聚合字段
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
product:"Bike"
|
|
|
|
|
sku:“abc123456”
|
|
|
|
|
quantitiy:20394,
|
|
|
|
|
daily_sales: 40,
|
|
|
|
|
weekly sales:302,
|
|
|
|
|
monthly_sales:1419
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
```spring-mongodb-json
|
|
|
|
|
db.inventory.update({_id:123},{
|
|
|
|
|
$inc:{
|
|
|
|
|
quantity:-1,
|
|
|
|
|
daily_sales: 1,
|
|
|
|
|
weekly_sales:1,
|
|
|
|
|
monthly_sales: 1
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
- 模式小结: 预聚合
|
|
|
|
|
- 场景: 准确排名, 排行榜
|
|
|
|
|
- 痛点: 统计计算耗时, 计算时间长
|
|
|
|
|
- 设计模式方案及优点: 模型中直接增加统计字段, 每次更新数据时候同时更新统计值
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|