概述
继续跟中华石杉老师学习ES,第54篇
课程地址: https://www.roncoo.com/view/55
关系型与document类型数据模型对比
举个例子: 部门和员工 ,1个部门下可以有N多个员工 ,部门:员工 = 1:N 1对多的关系。
关系型数据库
部门Department 表
dept_id name desc
员工Employee 表 (通过dept_id关联到所属的部门)
emp_id name age gender dept_id
数据库的设计还是遵循了三范式:将每个数据实体拆分为一个独立的数据表,同时使用主外键关联关系将多个数据表关联起来 , 确保没有任何冗余的数据 .
一份数据,只会放在一个数据表中,比如dept name,部门名称,就只会放在department表中,不会在employee表中也放一个dept name,如果说你要查看某个员工的部门名称,那么必须通过员工表中的外键,dept_id,找到在部门表中对应的记录,然后找到部门名称 。
应用Model
/** * 部门 **/ public class Department { private Integer deptId; private String name; private String desc; // 部门中存放一个 员工的集合 private List<Employee> employees; } /** * 员工 **/ public class Employee { private Integer empId; private String name; private Integer age; private String gender; // 所在部门 private Department dept; }
es文档数据模型
{ "deptId": "1", "name": "研发部门", "desc": "负责公司的所有研发项目", "employees": [ { "empId": "1", "name": "张三", "age": 28, "gender": "男" }, { "empId": "2", "name": "王兰", "age": 25, "gender": "女" }, { "empId": "3", "name": "李四", "age": 34, "gender": "男" } ] }
es更加类似于面向对象的数据模型,将所有由关联关系的数据,放在一个doc json类型数据中,整个数据的关系,还有完整的数据,都放在了一起.
建模方式一:通过应用层join实现用户与博客的关联
构造用户与博客数据
# 让ES自动创建 users索引,并写入一条数据 PUT /users/users/1 { "name": "小工匠", "email": "artisan@artisan.com", "birthday": "2000-01-01" } #让ES自动创建 blogs ,并写入一条数据 PUT /blogs/blogs/1 { "title": "跟石杉老师学ES", "content": "数据建模之通过【应用层join】或者【数据冗余】实现实现用户与博客的关联", "userId": 1 }
搜索某个用户发表的所有博客
# 第一次搜索 查询name为 小工匠的用户 (这里需要name.keyword 不分词查询) GET /users/users/_search { "query": { "term": { "name.keyword": { "value": "小工匠" } } } }
# 第二次搜索,要放入terms中userId GET /blogs/blogs/_search { "query": { "bool": { "filter": { "terms": { "userId": [ 1 ] } } } } }
假设搜索的是,1万个用户的博客,可能第一次搜索,会得到1万个userId , 第二次搜索的时候,要放入terms中1万个userId,才能进行搜索,这个时候性能比较差了 。
优缺点
- 优点:数据不冗余,维护方便
- 缺点:应用层join,如果关联数据过多,导致查询过大,性能很差
建模方式二:通过数据冗余实现用户与博客的关联
第二种建模方式:用冗余数据,采用文档数据模型,进行数据建模,实现用户和博客的关联, 在ES的应用中,推荐这种方式建模。
构造用户与博客数据
# 让ES自动创建 users2索引,并写入一条数据 PUT /users2/users2/1 { "name": "小工匠", "email": "artisan@artisan.com", "birthday": "2000-01-01" } #让ES自动创建 blogs2 ,并写入一条数据 PUT /blogs2/blogs2/1 { "title": "跟石杉老师学ES", "content": "数据建模之通过【应用层join】或者【数据冗余】实现实现用户与博客的关联", "userInfo": { "userId": 1, "username": "小工匠" } }
冗余数据就是说将可能会进行搜索的条件和要搜索的数据,放在一个doc中
搜索某个用户发表的所有博客
GET /blogs2/blogs2/_search { "query": { "term": { "userInfo.username.keyword": { "value": "小工匠" } } } }
可以看到不需要走应用层的join,先搜一个数据,找到id,再去搜另一份数据,直接走一个有冗余数据的type即可,指定要的搜索条件,即可搜索出自己想要的数据来。
优点和缺点
- 优点:性能高,不需要执行两次搜索
- 缺点:数据冗余,维护成本高 ,每次username变化了,同时要更新user type和blog type
一般来说,对于es这种NoSQL类型的数据存储来讲,都是冗余模式…
当然,我们要去维护数据的关联关系,也是很有必要的,所以一旦出现冗余数据的修改,必须记得将所有关联的数据全部更新。



