我们如何把Mysql的模型合理的在ES中去实现? 就需要你对要存储的数据足够的了解,及对应用场景足够的深入分析,才能建立一个合适的模型,便于你后期扩展
上一篇,我们介绍了 一对多模型,采用Object对象存储的巨大缺陷,本篇文章,我们给出解决办法 就是采用Nested结构来存储数据, 但是Nested查询和读写需要有特定的语法,也就是一定程度上增加了读写的复杂性,但是数据的查询结果是正确的,所以说Nested 才是我们一对多 推荐的一种设计模型
我们采用下面创建Index mapping结构,和上一篇大致一样的结构,把多个手机相同的分类信息,作为冗余字段 冗余到 手机基本信息中
差别就是 : 这次category字段,我们采用Nested结构,而不是Object结构,通过关键字 type:nested 来实现
索引库结构
PUT /phone_nested_index
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 2
},
"mappings": {
"properties": {
"productId": {
"type": "long"
},
"productName": {
"type": "keyword"
},
"productPrice": {
"type": "long"
},
"productNumber": {
"type": "long"
},
"category": {
"type": "nested",
"properties": {
"categoryName": {
"type": "keyword"
},
"categoryRemark": {
"type": "keyword"
}
}
}
}
}
}
同样的,插入数据, 下面我们给 phone_index 索引库插入数据, 插入 6条手机信息
put /phone_nested_index/_bulk
{"index":{"_id":1}}
{"productId":1,"productName":"P20","productPrice":4000,"productNumber":50,"category":{"categoryName":"华为手机","categoryRemark":"高端"}}
{"index":{"_id":2}}
{"productId":2,"productName":"Honor30","productPrice":2000,"productNumber":100,"category":[{"categoryName":"华为手机","categoryRemark":"很好"},{"categoryName":"荣耀手机","categoryRemark":"便宜"}]}
{"index":{"_id":3}}
{"productId":3,"productName":"小米8","productPrice":2000,"productNumber":600,"category":{"categoryName":"小米手机","categoryRemark":"中端"}}
{"index":{"_id":4}}
{"productId":4,"productName":"红米10","productPrice":2500,"productNumber":300,"category":{"categoryName":"小米手机","categoryRemark":"发烧"}}
{"index":{"_id":5}}
{"productId":5,"productName":"小米Max","productPrice":4000,"productNumber":800,"category":{"categoryName":"小米手机","categoryRemark":"很好"}}
我们要查询 华为手机 便宜的 标签,must 查询, 分类:华为手机,描述:便宜
Nested结构查询,需要特定的语法,需要加上查询路径,我们的就是 path:category 信息
老的结构 非Nested phone_index 数据
get /phone_index/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"category.categoryName": "华为手机"
}
},
{
"match": {
"category.categoryRemark": "便宜"
}
}
]
}
}
}
或者 我们再查询以下 华为手机-发烧的 场景, 按照我们的数据, 不存在任何数据把华为手机和发烧关联
must查询, 分类:华为手机, 标签:发烧
get /phone_index/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"category.categoryName": "华为手机"
}
},
{
"match": {
"category.categoryRemark": "发烧"
}
}
]
}
}
}
查询结果错误, 要查询 华为手机-发烧的数据,结果把 小米手机查询出来了,这是明显的错误
同样,我们采用Nested结构查询, 查询华为手机 且便宜的 信息
Nested结构查询,需要带上查询条件 path路径信息 “nested”: {“path”: “category”}
get /phone_nested_index/_search
{
"query": {
"nested": {
"path": "category",
"query": {
"bool": {
"must": [
{
"match": {
"category.categoryName": "华为手机"
}
},
{
"match": {
"category.categoryRemark": "便宜"
}
}
]
}
}
}
}
}
查询结果, 符合预期,并没有查询出 错误的结果, 查询结果为空
现在我们来查以下另一种场景, 华为手机-发烧 的查询语句,看看是否能够正确查询
get /phone_nested_index/_search
{
"query": {
"nested": {
"path": "category",
"query": {
"bool": {
"must": [
{
"match": {
"category.categoryName": "华为手机"
}
},
{
"match": {
"category.categoryRemark": "发烧"
}
}
]
}
}
}
}
}
同样的结果,查询结果没有数据, 也是符合我们预期的,是正确的查询结果
上面我们验证了采用Nested 结构,可以有效的解决 object对象存储, 错误的查询方式这种缺陷,那么原理是什么呢?
官方定义:官方释义:
这样就可以解决Object对象存储的问题