大型商城:商城业务-商品上架
ES储存分析
需要存储那些信息到ES中去
- 需要保存sku信息
- 当搜索商品名的时候,检索到的是sku的sku_title
- 还会通过sku的销量、标题、价格区间来进行检索
- 需要保存品牌分类等信息
- 点击分类,检索分类下的所有信息
- 点击品牌,检索品牌下的商品信息
- 需要保存spu的规格信息——选择规格的时候会检索共有这些规格的spu信息
如何设计存储结构 商品Mapping
1.将sku的全量信息保存进去,包括spu的属性 造成空间冗余
// 优点:方便检索
// 缺点:会产生冗余字段,对于属于同一spu的商品,attrs字段数据会冗余
举例
{
skuId:1
spuId:11
skuTitle:"华为xx"
price:998
saleCount:99
attrs:[
{尺寸:"5寸"},
{CPU:高通945},
{分辨率:全高清}
]
}
2.分拆存储,spu 和 attr 一个索引,sku 单独一个索引可能涉及的问题。
// 优点:空间利用率高
// 缺点:查询attr时,会检索当前所有的spu,耗时很长
举例
建一个sku索引,只保存非冗余字段
{
skuId:1
spuId:11
xxxx
}
再建一个attr索引
{
spuId:11
attrs:[
{尺寸:"5寸"},
{CPU:高通945},
{分辨率:全高清}
]
}
假设搜索小米, 粮食、手机、电器等有很多sku都包含有小米
10000个包含小米的sku,涉及到4000个spu,我们会找到4000个spu的attr进行聚合,通过分步查询:
1. 查出包含小米的10000个sku,其涉及到4000个spu
2. 查出4000个spu对应的所有可能属性 esClient:spuId:[4000个spuId] 4000*8=32000byte=32kb
32kb*10000=320mb; 如果是百万并发会发送32GB的数据
检索商品的名字,如“手机”,对应的 spu 有很多,我们要分析出这些 spu 的所有关联属性,再做一次查询,就必须将所有 spu_id 都发出去。假设有 1 万个数据,数据传输一次就10000*4=4MB;并发情况下假设 1000 检索请求,那就是 4GB 的数据,传输阻塞时间会很长,业务更加无法继续。
3.如下设计,这样才是文档区别于关系型数据库的地方,宽表设计,不能去考虑数据库范式。
最终方案
PUT product
{
"mappings": {
"properties": {
"skuId": { "type": "long" },
"spuId": { "type": "keyword" },
"skuTitle": {
"type": "text",
"analyzer": "ik_smart"
},
"skuPrice": { "type": "keyword" },
"skuImg": {
"type": "keyword",
"index": false,
"doc_values": false # 表示该属性不需要聚合等操作
},
"saleCount":{ "type":"long" },
"hasStock": { "type": "boolean" },
"hotScore": { "type": "long" },
"brandId": { "type": "long" },
"catalogId": { "type": "long" },
"brandName": {
"type": "keyword",
"index": false,
"doc_values": false
},
"brandImg":{ # 品牌图片,只用来查看,不用来检索和聚合
"type": "keyword",
"index": false,
"doc_values": false
},
"catalogName": {
"type": "keyword",
"index": false,
"doc_values": false
},
"attrs": { # 这里是spu的规格属性
"type": "nested", # 嵌入式,内部属性
"properties": {
"attrId": {"type": "long" },
"attrName": {
"type": "keyword",
"index": false,
"doc_values": false
},
"attrValue": { "type": "keyword" }
}
}
}
}
}
关于nested类型
- Object 数据类型的数组会被扁平化处理为一个简单的键与值的列表,即对象的相同属性会放到同一个数组中,在检索时会出现错误。 对象类型的数组如何被扁平化处理
- 对于 Object 类型的数组,要使用 nested 字段类型。避免扁平化处理........Using nested fields for arrays of objects
将user的type修改为 nested ,不进行扁平化处理,就不会发生以上情况!
PUT my_index/_mapping
{
"mapping":{
"properties":{
"user":{
"type":"nested"
}
}
}
}
商品上架功能
点击商家把相关信息保存到es中,再修改商品状态
详细代码:com.tinstu.gulimall.product.service.impl.SpuInfoServiceImpl 中的up方法!
feign的调用流程
/**
* Feign 调用流程
* 1.构造请求数据,将对象转换为json
* RequestTemplate template = buildTemplateFromArgs.create(argv);
* 2.发送请求进行执行(执行成功会解码响应数据)
* executeAndDecode(template);
* 3.执行请求会有重试机制
* while(true){
* try{
* executeAndDecode(template);
* }catch(){
* try{
* retryer.continueOrPropagate(e);
* } catch(){
* throw ex;
* }
* comtinue;
* }
* }
*/
阅读剩余
版权声明:
作者:Tin
链接:http://www.tinstu.com/2618.html
文章版权归作者所有,未经允许请勿转载。
THE END