概要
本篇以实际案例为背景,介绍不同技术组件对数据建模的特点,并以ES为背景,介绍常用的联合查询的利弊,最后介绍了一下文件系统分词器path_hierarchy和嵌套对象的使用。
数据模型对比
实际项目中,电商平台系统常见的组合Java、Mysql和Elasticsearch,以基础的部门-员工实体为案例。
JavaBean类型定义
如果是JavaBean类型,会这样定义
public class Department {
private Long id;
private String name;
private String desc;
private List<Long> userIds;
}
public class Employee {
private Long id;
private String name;
private byte gender;
private Department dept;
}
数据库模型定义
如果是关系型数据库(mysql),会这样建表
create table t_department (
id bigint(20) not null auto_increment,
name varchar(30) not null,
desc varchar(80) not null,
PRIMARY KEY (`id`)
)
create table t_employee (
id bigint(20) not null auto_increment,
name varchar(30) not null,
gender tinyint(1) not null,
dept_id bigint(20),
PRIMARY KEY (`id`)
)
依据数据库三范式设计表,每个实体设计成独立的表,用主外键约束进行关联,按照现有的数据表规范,已经不再使用外键约束了,外键约束放在应用层控制。
ES文档数据模型
如果es的文档数据模型,会这样设计document
{
"deptId": 1,
"deptname": "CEO办公室",
"desc":"这一个有情怀的CEO",
"employee":[
{
"userId":1,
"name":Lily,
"gender":0
},
{
"userId":2,
"name":Lucy,
"gender":0
},
{
"userId":3,
"name":Tom,
"gender":1
}
]
}
es更类似面向对象的数据模型,将所有关联的数据放在一个document里。
JOIN查询
我们以博客网站为案例背景,建立博客网站中博客与用户的数据模型。
将用户与博客分别建立document,分割实体,类似数据库三范式,并使用关键field(userId)建立依赖关系
先建立两个实体document,放一条示例数据
PUT /blog/user/1
{
"id":1,
"username":"Lily",
"age":18
}
PUT /website/article/1
{
"title":"my frist blog",
"content":"this is my first blog, thank you",
"userId":1
}
需求:要查询用户名Lily发表的博客
步骤:1)查询用户document,根据名字Lily查询到它的userId;
2)根据第一步查询返回的userId,重新组装请求报文,查询博客docuement
示例报文:
GET /blog/user/_search
{
"query": {
"match": {
"username.keyword": "Lily"
}
}
}
GET /website/article/_search
{
"query": {
"constant_score": {
"filter": {
"terms": {
"userId":