Elasticsearch进阶笔记第二十八篇

105 阅读4分钟

Elasticsearch高手进阶篇(59)

数据建模实战_关系型与document类型数据模型对比

关系型数据库的数据模型

  • department的结构
 public class Department {
     private Integer deptId;
     private String name;
     private String desc;
     private List<Employee> employees;
 }
  • employee的结构
 public class Employee {
     private Integer empId;
     private String name;
     private Integer age;
     private String gender;
     private Department dept;
 }

关系型数据库中

  • department表

    • dept_id
    • name
    • desc
  • employee表

    • emp_id
    • name
    • age
    • gender
    • dept_id
  • 三范式

    • 将每个数据实体拆分为一个独立的数据表,同时使用主外键关联关系将多个数据表关联起来 --> 确保没有任何冗余的数据
  • 一份数据,只会放在一个数据表中 --> dept name,部门名称,就只会放在department表中,不会在employee表中也放一个dept name,如果说你要查看某个员工的部门名称,那么必须通过员工表中的外键,dept_id,找到在部门表中对应的记录,然后找到部门名称

es文档数据模型

 {
     "deptId": "1",
     "name": "研发部门",
     "desc": "负责公司的所有研发项目",
     "employees": [
         {
             "empId": "1",
             "name": "waws1",
             "age": 18,
             "gender": "男"
         },
         {
             "empId": "2",
             "name": "waws2",
             "age": 26,
             "gender": "女"
         },
         {
             "empId": "3",
             "name": "waws3",
             "age": 36,
             "gender": "男"
         }
     ]
 }
  • es,更加类似于面向对象的数据模型,将所有由关联关系的数据,放在一个doc json类型数据中,整个数据的关系,还有完整的数据,都放在了一起

Elasticsearch高手进阶篇(60)

数据建模实战_通过应用层join实现用户与博客的关联

构造用户与博客数据

在构造数据模型的时候,还是将有关联关系的数据,然后分割为不同的实体,类似于关系型数据库中的模型

案例背景:博客网站, 我们会模拟各种用户发表各种博客,然后针对用户和博客之间的关系进行数据建模,同时针对建模好的数据执行各种搜索/聚合的操作

 PUT /waws_webblog/users/1 
 {
   "name":"waws",
   "email":"waws@sina.com",
   "birthday":"1980-01-01"
 }
 
 PUT /waws_webblog/blogs/1
 {
   "title":"waws第一篇博客",
   "content":"waws第一篇博客,开通啦!",
   "userId":1 
 }

一个用户对应多个博客,一对多的关系,做了建模

建模方式,分割实体,类似三范式的方式,用主外键关联关系,将多个实体关联起来

搜索waws发表的所有博客

  • 比如这里搜索的是,1万个用户的博客,可能第一次搜索,会得到1万个userId
 GET /waws_webblog/users/_search 
 {
   "query": {
     "term": {
       "name.keyword": {
         "value": "waws"
       }
     }
   }
 }
 
 {
   "took": 27,
   "timed_out": false,
   "_shards": {
     "total": 5,
     "successful": 5,
     "failed": 0
   },
   "hits": {
     "total": 1,
     "max_score": 0.2876821,
     "hits": [
       {
         "_index": "waws_webblog",
         "_type": "users",
         "_id": "1",
         "_score": 0.2876821,
         "_source": {
           "name": "waws",
           "email": "waws@sina.com",
           "birthday": "1980-01-01"
         }
       }
     ]
   }
 }
  • 第二次搜索的时候,要放入terms中1万个userId,才能进行搜索,这个时候性能比较差了
 GET /waws_webblog/blogs/_search 
 {
   "query": {
     "constant_score": {
       "filter": {
         "terms": {
           "userId": [
             1
           ]
         }
       }
     }
   }
 }
 
 {
   "took": 22,
   "timed_out": false,
   "_shards": {
     "total": 5,
     "successful": 5,
     "failed": 0
   },
   "hits": {
     "total": 1,
     "max_score": 1,
     "hits": [
       {
         "_index": "waws_webblog",
         "_type": "blogs",
         "_id": "1",
         "_score": 1,
         "_source": {
           "title": "waws第一篇博客",
           "content": "waws第一篇博客,开通啦!",
           "userId": 1
         }
       }
     ]
   }
 }

上面的操作,就属于应用层的join,在应用层先查出一份数据,然后再查出一份数据,进行关联

优点和缺点

  • 优点:数据不冗余,维护方便
  • 缺点:应用层join,如果关联数据过多,导致查询过大,性能很差

Elasticsearch高手进阶篇(61)

数据建模实战_通过数据冗余实现用户与博客的关联

构造冗余的用户和博客数据

第二种建模方式:用冗余数据,采用文档数据模型,进行数据建模,实现用户和博客的关联

 PUT /waws_webblog/users/1
 {
   "name":"waws",
   "email":"waws@sina.com",
   "birthday":"1980-01-01"
 }
 
 PUT /waws_webblog/blogs/1
 {
   "title": "waws的第一篇博客",
   "content": "大家好,我是waws",
   "userInfo": {
     "userId": 1,
     "username": "waws"
   }
 }
  • 冗余数据,就是说,将可能会进行搜索的条件和要搜索的数据,放在一个doc中

基于冗余用户数据搜索博客

 GET /waws_webblog/blogs/_search 
 {
   "query": {
     "term": {
       "userInfo.username.keyword": {
         "value": "waws"
       }
     }
   }
 }
 
 {
   "took": 3,
   "timed_out": false,
   "_shards": {
     "total": 5,
     "successful": 5,
     "failed": 0
   },
   "hits": {
     "total": 1,
     "max_score": 0.2876821,
     "hits": [
       {
         "_index": "waws_webblog",
         "_type": "blogs",
         "_id": "1",
         "_score": 0.2876821,
         "_source": {
           "title": "waws的第一篇博客",
           "content": "大家好,我是waws",
           "userInfo": {
             "userId": 1,
             "username": "waws"
           }
         }
       }
     ]
   }
 }

就不需要走应用层的join,先搜一个数据,找到id,再去搜另一份数据

直接走一个有冗余数据的type即可,指定要的搜索条件,即可搜索出自己想要的数据来

优点和缺点

优点:性能高,不需要执行两次搜索 缺点:数据冗余,维护成本高 --> 每次如果你的username变化了,同时要更新user type和blog type

一般来说,对于es这种NoSQL类型的数据存储来讲,都是冗余模式....

当然,你要去维护数据的关联关系,也是很有必要的,所以一旦出现冗余数据的修改,必须记得将所有关联的数据全部更新