SKU聚合SPU算法
1. 问题背景
商品结构包含SKU和SPU,淘宝的商品展示是基于SPU,京东的商品展示基于SKU。这两种展示方式各有什么优缺点。
1.1. 基于SKU的展示方式
SKU展示的优点:
可以过滤SKU的特性(规格、库存等)
用户最终购买的都是SKU,规格、库存等特性也是SKU上的,筛选和过滤条件可以控制到规格等SKU属性。比如搜索“iPhone 6s 银色 16G”,可以直接展示该SKU,过滤掉其它颜色、其它容量的6s SKU。这种过滤方式对服装行业是很有用的,服装通常一个SPU下面有几十个SKU,我们搜索会加上想要的颜色、尺寸等规格。
可以更精确地建立用户画像
一个用户买衣服时经常选择颜色为黑色、尺寸为XXXL,那么我们给用户建立的画像就是喜好黑色、本人衣服尺寸为XXXL。这样后续推荐商品可以推荐这些规格的衣服给他;或者做千人千面个性化搜索时,可以把这些规格的衣服权重调搞,排在页面的前面。
SKU展示的缺点
同一个SPU下面SKU很多时,列表展示的都是同一个SPU下的SKU
京东搜索“马牌轮胎”关键词,出来的SKU列表如下图:
前面5个SKU属于同一个SPU,前面10个SKU有8个属于同一个SPU,只是轮胎的尺寸不同。如果是服装类SPU,旗下的SKU会更多,这样可能一页都属于同一个SPU。
1.2. 基于SPU的展示方式
SPU展示的优点
每页可以展示更多的信息,给用户更多的选择空间
正常我们搜索商品时可能只会浏览前面几页的商品数据,更多情况下可能就第一页的商品。这时展示更多的商品就很重要了,可能会提升客户的购买率。
SPU展示的缺点
无法筛选规格
当用户购买衣服时,可能只关心自己的颜色和Size,基于SPU展示方式无法做到这一点,并且某个规格下的SKU可能没货,也需要点击进详情页才能知道。
2. 问题分析
既然SKU和SPU展示都有各自的优缺点,是否有一种展示方式能够吸取这两种方式的优点呢。我们可以看下京东手机类目下的搜索:
京东输入“iphone 6s”,展示的结果如下:
如果我们只对金色感兴趣,输入关键词“iphone 6s 金色”,展示的结果如下:
我们来分析一下京东的这种展示方式:
商品展示列表是以SPU纬度的。
否则搜索“iphone 6s”时,前面的SKU肯定是京东自营的“iphone 6s 64G 银色”、“iphone 6s 64G 金色”、“iphone 6s 64G 灰色”、“iphone 6s 64G 玫瑰金色”、“iphone 6s 16G 银色”、“iphone 6s 16G 金色”、“iphone 6s 16G 灰色”、“iphone 6s 16G 玫瑰金色”等。商品展示SPU下的SKU是根据搜索条件动态变化的
搜索“iphone 6s”时,SPU下面的SKU有4个,分别对应4种颜色;搜索“iphone 6s 金色”时,SPU下面的SKU只有两个“金色”、“玫瑰金”。这样用户很清楚就可以找到符合要求的商品。商品的分页信息也是SPU纬度的。
一共71个商品,2页,71显然是SPU数目。商品的筛选条件是基于SKU纬度的
如果筛选条件是基于SPU的,那么搜索“iphone 6s”和搜索“iphone 6s 玫瑰金”这两个关键词,符合条件的SPU应该是相同的,筛选条件也应该是相同的,事实却不是这样。可以看到京东的这种展示方式融合了SPU展示和SKU展示的优点,对于数码3C、服装、快消品等行业是最佳展示方式。
3. 解决方案
通过上面的分析可知,我们只要将搜索和聚合作用于SKU,然后将符合条件的SKU按照SPU纬度做个分组(sku groupBy spu ),然后获取SPU的分页信息即可。
3.1 算法简要步骤
搜索和聚合SKU
根据搜索请求参数,获取符合条件的SKU和相应聚合条件。搜索时,采用scan方式,将SKU加载在内存中。聚合条件增加spuId字段cardinality方式的聚合。
按照SPU纬度分组SKU
对SKU进行GroupBy spuId操作,不需要对所有SKU进行操作,只需要对分页要求的SPU进行。
根据ID查找SPU
根据步骤2获取的SKU分组中的spuId,根据ID查询对应的SPU数据结构。
zip压缩SPU、SKU
对步骤2获取的SKU、步骤3获取的SPU进行zip压缩操作,形成的SPU结构为:{spuId:11111, k1:v1, k2:v2, skuList:[sku1, sku2]}。最终返回数据结构为:{total: 120, root:[spu1, spu2, ...]}