✅P128-129_商城业务-商品上架-sku在es中存储模型分析

gong_yz大约 3 分钟谷粒商城

商品部分信息存储在es中

保存 sku 信息

当搜索商品名时,查询的是 sku 的标题 sku_title;

可能通过 sku 的标题、销量、价格区间检索。

保存品牌、分类信息

点击分类,检索分类下的所有信息。

点击品牌,检索品牌下的商品信息。

保存 spu 信息

选择规格,检索共有这些规格的商品。


商品 Mapping

存储结构方案

空间换时间

缺点:会产生冗余字段,对于相同类型的商品,attrs 属性字段会重复,空间占用大好处:方便检索

{
    skuId:1
    spuId:11
    skuTitile:华为xx
    price:999
    saleCount:99
    attrs:[
        {尺寸:5},
        {CPU:高通945},
        {分辨率:全高清}
	 ]
}

时间换空间

缺点:选择公共属性attr时,会检索当前属性的所有商品分类,然后再查询当前商品分类的所有可能属性;导致耗时长。

好处:空间利用率高

sku索引 
{
    skuId:1
    spuId:11
}
attr索引
{
    spuId:11
    attrs:[
        {尺寸:5},
        {CPU:高通945},
        {分辨率:全高清}
		]
}

因此,选择第一种存储模型.

最终商品Mapping设计

分析:keyword不全文检索,text全文检索,价格使用keyword为了保存精度,hasStock表示库存,hotScore表示热度,只用于显示的数据将index和doc_values设置为false表示不参与检索和聚合

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": {
        "type": "nested",
        "properties": {
          "attrId": {
            "type": "long"
          },
          "attrName": {
            "type": "keyword",
            "index": false,
            "doc_values": false
          },
          "attrValue": {
            "type": "keyword"
          }
        }
      }
    }
  }
}

mapping结构字段说明

index

默认 true, 如果为 false, 表示该字段不会被索引, 但是检索结果里面有, 但字段本身不能当做检索条件。

doc_values

默认 true, 设置为 false, 表示不可以做排序、 聚合以及脚本操作, 这样更节省磁盘空间。还可以通过设定 doc_values 为 true, index 为 false 来让字段不能被搜索但可以用于排序、 聚合以及脚本操作。

"mappings": {
  "properties": {
    "skuId": { "type": "long" },
    "spuId": { "type": "keyword" }, # 精确检索,不分词
    "skuTitle": {
      "type": "text", # 全文检索
      "analyzer": "ik_smart" # 分词器
    },
    "skuPrice": { "type": "keyword" },
    "skuImg": {
      "type": "keyword",
      "index": false, # false 不可被检索
      "doc_values": false # false 不可被聚合
    },
    "saleCount":{ "type":"long" }, # 商品销量
    "hasStock": { "type": "boolean" }, # 商品是否有库存
    "hotScore": { "type": "long"  }, # 商品热度评分
    "brandId":  { "type": "long" }, # 品牌id
    "catalogId": { "type": "long"  }, # 分类id
    "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": {	# 属性对象
      "type": "nested",	# 嵌入式,内部属性
      "properties": {
        "attrId": {"type": "long"  },
        "attrName": {	# 属性名
          "type": "keyword",
          "index": false,
          "doc_values": false
        },
        "attrValue": { "type": "keyword" }	# 属性值
      }
    }
  }
}

Es-数组的扁平化处理

Object 数据类型的数组会被扁平化处理为一个简单的键与值的列表,即对象的相同属性会放到同一个数组中,在检索时会出现不存在的数据被检索到。参考官网:How arrays of objects are flattenedopen in new window


nested 类型

对于 Object 类型的数组,要使用 nested 字段类型。参考官网:Using nested fields for arrays of objectsopen in new window

举例:

  "attrs": {	# 属性对象
      "type": "nested",	# 嵌入式,内部属性
      "properties": {
        "attrId": {"type": "long"  },
        "attrName": {	# 属性名
          "type": "keyword",
          "index": false,
          "doc_values": false
        },
        "attrValue": { "type": "keyword" }	# 属性值
      }
    }