在电商搜索、商品列表分页、活动商品召回等核心场景中,search-after 凭借无深度分页性能衰减、支持实时数据查询的优势,成为开发者的首选分页方案。但实际运营中,很多团队会遇到「符合条件的商品漏展示」的问题 ------ 比如重复上架的同款商品、新品无法被用户看到,这大概率是排序字段组合选型不当导致的。
尤其在「存在大量同款商品」的电商场景(如同一品牌的同款服饰、商家重复上架的商品),_score+create_time 的排序效果远优于 _score+seq_no。本文将结合电商实际业务案例,拆解两种排序组合的差异,告诉你为什么前者能避免商品漏展示,后者却容易踩坑。
一、核心前提:search-after 漏召的唯一根源
在分析字段差异前,必须先明确 search-after 的工作原理:search-after 是「游标式分页」,通过「上一页最后一条数据的排序值」定位下一页起点。如果存在多条商品的排序值完全相同,ES 无法区分它们的先后顺序,会误判 "排序值之后无更多数据",导致部分商品被跳过(漏展示) 。
因此,排序字段组合的核心要求是:必须能唯一标识每一件商品------ 这是避免商品漏展示的关键,直接影响用户浏览体验和商家销量。
二、电商场景定义:什么是「同款商品」?
本文讨论的「同款商品」,贴合电商实际业务场景:
- 核心信息一致:商品名称、主图、规格参数、价格等关键字段相同(可能是商家重复上架、品牌统一铺货的商品);
- 相关性得分相同:因商品信息一致,匹配用户搜索关键词(如 "2024 夏季纯棉 T 恤")的
_score(相关性得分)完全相同; - 业务属性有差异:即使是同款商品,上架时间(
create_time)必然不同(重复上架有先后顺序),但 ES 内部的seq_no(版本号)可能重复。
三、案例对比:两种排序组合的实际效果
假设某电商平台有 5 件「同款纯棉 T 恤」,核心字段如下表(贴合电商商品数据结构):
| 商品 ID | _score(搜索相关性) | seq_no(ES 内部版本号) | create_time(上架时间戳) | 商品说明 |
|---|---|---|---|---|
| P001 | 9.8 | 5 | 1730000000(2024-10-27) | 商家 A 上架的同款 T 恤 |
| P002 | 9.8 | 3 | 1730000001(2024-10-28) | 商家 B 上架的同款 T 恤 |
| P003 | 9.8 | 5 | 1730000002(2024-10-29) | 商家 A 重复上架的同款 T 恤 |
| P004 | 9.8 | 7 | 1730000003(2024-10-30) | 商家 C 上架的同款 T 恤 |
| P005 | 9.8 | 3 | 1730000004(2024-10-31) | 商家 D 上架的同款 T 恤 |
我们以「用户搜索 "纯棉 T 恤" 后分页浏览」为例,pageSize=2(模拟每页展示 2 件商品),分别测试两种排序组合的召回效果。
1. 排序组合一:_score + seq_no(容易漏展示商品)
(1)排序逻辑与结果
- 排序规则:先按
_score降序(所有商品都是 9.8,相关性一致),再按seq_no降序(7→5→5→3→3); - 实际排序结果:ES 对
seq_no相同的商品,按「分片内部默认顺序」排列(无电商业务意义),最终为:P004(9.8,7)→ P001(9.8,5)→ P003(9.8,5)→ P005(9.8,3)→ P002(9.8,3)
(2)分页召回过程(漏展示 P003)
- 第 1 页:返回 P004(商家 C 商品)、P001(商家 A 商品),客户端记录最后一条排序值
(9.8,5); - 第 2 页:携带
search_after: [9.8,5]请求,ES 查找「排序值严格小于 (9.8,5)」的商品; - 关键问题:P003(商家 A 重复上架商品)的排序值也是
(9.8,5),与上一页最后一条完全相同 ------ES 无法判断 P003 在 P001 之后,直接跳过 P003; - 第 2 页实际返回:P005(商家 D 商品)、P002(商家 B 商品);
- 第 3 页:携带
search_after: [9.8,3],无更多商品,返回空; - 最终结果:用户仅看到 P004、P001、P005、P002 4 件商品,P003 漏展示------ 商家 A 的重复上架商品无法被用户看到,直接影响商品曝光和销量。
(3)漏展示根源
seq_no是「分片级内部版本号」:ES 为每个分片独立分配seq_no,不同分片、不同商品可能出现相同seq_no(如 P001 和 P003);- 排序值重复:
_score相同 +seq_no重复,导致排序组合失去唯一性,ES 无法精准定位下一页起点,进而漏展示商品。
2. 排序组合二:_score + create_time(无漏展示)
(1)排序逻辑与结果
- 排序规则:先按
_score降序(所有商品都是 9.8),再按create_time降序(上架时间越新越靠前,符合电商 "新品优先" 运营逻辑); - 实际排序结果:无任何重复,顺序固定为:
P005(9.8,1730000004)→ P004(9.8,1730000003)→ P003(9.8,1730000002)→ P002(9.8,1730000001)→ P001(9.8,1730000000)
(2)分页召回过程(全量展示)
- 第 1 页:返回 P005(商家 D 新品)、P004(商家 C 新品),记录排序值
(9.8,1730000003); - 第 2 页:携带
search_after: [9.8,1730000003],ES 精准匹配「排序值 <(9.8,1730000003)」的商品,返回 P003(商家 A 重复上架商品)、P002(商家 B 商品); - 第 3 页:携带
search_after: [9.8,1730000001],返回 P001(商家 A 商品); - 最终结果:5 件商品全部展示,无漏展示、无重复 ------ 用户能按 "新品优先" 顺序看到所有同款商品,商家的商品曝光机会均等。
(3)无漏展示根源
create_time是「电商业务级唯一字段」:即使是同款商品,上架时间也必然不同(重复上架有先后顺序),天然具备全局唯一性;- 排序值绝对唯一:
_score + create_time的组合确保每件商品的排序值不重复,ES 能精准区分每一件商品的位置,同时符合电商 "新品优先" 的运营逻辑,提升用户体验。
四、seq_no 不适合电商场景的深层原因
很多开发者误以为 seq_no 是唯一的,但它的设计目的是「ES 内部版本控制」(如商品信息更新、删除时的冲突检测),而非电商业务排序,因此有三个致命缺陷:
- 非全局唯一 :
seq_no按分片分配,不同分片的商品可能有相同seq_no,无法满足电商商品唯一标识需求; - 稳定性差 :商品信息更新(如修改价格、库存)时,
seq_no会自动递增,导致同一商品的排序位置频繁变化,用户重复看到同一商品; - 无业务意义 :
seq_no与商品上架时间、销量、评分等电商核心属性无关,排序结果不符合 "新品优先""热销优先" 等运营需求。