什么是数据建模
- 数据建模(Data modeling),是创建数据模型的过程
- 数据模型是对真实世界进行抽象描述的一种工具和方法,实现对现实世界的映射
- 博客 / 作者 / 评论
- 三个过程:模型概念 => 逻辑模型 => 数据模型(第三范式)
- 数据模型:结合具体的数据库,在满足业务读写性能需求的前提下,确定最终的定义
- 数据模型是对真实世界进行抽象描述的一种工具和方法,实现对现实世界的映射
数据建模:功能需求 + 性能需求

数据建模示意图
需考虑模型的功能需求和性能需求
如何对字段进行建模
- 字段类型
- 是否要搜索及分词
- 是否要聚合及排序
- 是否要额外的存储
字段类型:Text vs Keyword
- Text
- 用于全文本字段,文本会被analyzer分词
- 默认不支持聚合分析及排序。需要设置fielddata为true
- Keyword
- 用于id,枚举及不需要分词的文本。例如电话,email地址,手机号码,邮政编码,性别等
- 适用于filter(精确匹配),Sorting和Aggregations
- 设置多字段类型
- 默认会为文本类型设置成text,并且设置一个keyword字段
- 在处理人类语言时,通过增加“英文”,“拼音”和“标准”分词器,提高搜索结构
字段类型:结构化数据
- 数值类型
- 尽量选择贴近的类型。例如可以使用byte,就不要用long
- 枚举类型
- 设置为keyword。即便是数字,也应该设置成keyword,获取更好的性能
- 其他
- 日志 / 布尔 / 地理信息
检索
- 如不需要检索,排序和聚合分析
- Enable设置为false
- 如不需要检索
- Index设置为false
- 对需要检索的字段,可以通过如下配置,设定存储粒度
- index_options / Norms:不需要归一化数据时,可以关闭
聚合及排序
- 如不需要检索,排序和聚合分析
- Enable设置为false
- 如不需要排序或者聚合分析功能
- Doc_values / fielddata 设置为false
- 更新频繁,聚合查询频繁的keyword类型的字段
- 推荐将eager_global_oridinals设置为true
额外的存储
- 是否需要专门存储当前字段数据
- Store设置为true,可以存储该字段的原始内容
- 一般结合_source的enabled为false时候使用
- Disable _source:节约磁盘;适用于指标型数据
- 一般建议先考虑增加压缩比
- 无法看到_source字段,无法做ReIndex,无法做Update
一个数据建模的实例
- 图书的索引
- 书名
- 简介
- 作者
- 发行日期
- 图书封面
PUT book/_doc/1
{
"title": "mastering elasticsearch 5.0",
"description": "master the search indexing, and aggregation features in elasticsearch Improve users search experience with elasticsearch`s functionalities and develop your own elasticsearch plugins",
"author": "Bharvi Dixit",
"public_date": "2017",
"cover_url": "https://images.xxx.com/images/1/xxxx.jpg"
}

默认文本mapping
优化字段设定
- 图书的索引
- 书名:支持全文和精确匹配
- 简介:支持全文
- 作者:精确值
- 发型日期:日期类型
- 图书封面:精确值

修正后mapping
封面无需索引,index可以设置为false

对封面搜索报错

支持进行聚合
需求变更
- 新需求:增加图书内容的字段。并要求能被搜索同时,支持高亮显示
- 新需求会导致_source的内容过大
- Source Filtering只是传输给客户端时进行过滤,Fetch数据时,ES节点还是会传输_source中的数据
- 解决方法
- 关闭_source
- 然后将每个字段的“store”设置为true
mapping更新如下:
PUT books
{
"mappings": {
"_source": {"enabled": false},
"properties": {
"author": {
"type": "keyword"
},
"cover_url": {
"type": "keyword",
"index": false
},
"description": {
"type": "text"
},
"public_date": {
"type": "date"
},
"title": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 100
}
},
"store": true
},
"content": {
"type": "text",
"store": true
}
}
}
}
查询图书:解决字段过大引发的性能问题
- 返回结果不包含_source字段
- 对于需要显示的信息,可以在查询中指定“stored_fields”
- 禁止_source字段后,还是支持使用highlights API高亮,高亮显示content中匹配的相关信息

查询示例
Mapping字段的相关设定
-
https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-params.html
- Enabled:设置为false,仅做存储,不支持搜索和聚合分析(数据保存在_source中)
- Index:是否构倒排索引。设置为false,无法被搜索,但还是支持aggregation,并出现在_source中
- Norms:如果字段用来过滤和聚合分析,可以关闭,节约存储
- Doc_values:是否启用doc_values,用于排序和倒排分析
- field_data:如果要对text类型启用排序和聚合分析,fielddata需要设置成true
- Store:默认不存储,数据默认存储在_source中
- Coerce:默认开启,是否开启数据类型的自动转换(例如:字符串转数字)
- Multifields:多字段特性
- Dynamic:true / false / strict控制Mapping的自动更新
一些相关api
- Index Template & Dynamic Template
- 根据索引的名字匹配不同的Mappings和Settings
- 可以在一个Mapping上动态的设定字段类型
- Index Alias
- 无需停机,无需修改程序,即可进行修改
- Update by query & Reindex