本系列的第 1 至第 5 部分介绍了一个受治理控制平面,它在查询产品目录之前,完成意图分类、约束强制执行、策略冲突解决以及路由到适当的检索策略。到目前为止描述的所有机制都等同对待所有购物者。无论购物者是素食者、为孩子购买生日礼物的家长,还是遵守清真饮食规定的消费者,搜索“巧克力”都会产生相同的结果集。
本文介绍了两种个性化机制,它们可在不改变治理控制平面架构的前提下对其进行扩展。这两种机制与第 1 至第 5 部分的治理层叠加:策略仍会触发,约束仍会执行,冲突仍会解决,个性化信号被组合成同一治理查询,确保 Elasticsearch 返回的结果已经个性化。
第一种机制会提升购物者之前购买过的产品。第二种机制则根据购物者资料激活针对特定群组的策略。两者共同表明:个性化并非一个独立于搜索之外、或作为检索后处理来附加的系统,而是策略驱动的控制平面的一种自然扩展。
如需深入了解本文中使用的个性化技术的数学原理,请参阅《无需 ML 后处理的 Elasticsearch 个性化搜索》和《Elasticsearch 中基于群组感知的排名》。
要观看关于如何使用购买历史记录提升回头客搜索结果的现场演示,请观看视频:可解释的个性化:利用购买历史记录提升搜索结果。
个人购买历史记录提升
最简单的个性化推荐方式也是最有效的之一:如果购物者之前购买过某款产品,当他们搜索相关商品时,就提升该产品。一个经常购买某品牌巧克力曲奇的购物者,在搜索“曲奇”时,应该看到这些曲奇排名更靠前——这不是因为模型预测了偏好,而是因为有直接的行为证据。
运作方式
当搜索请求包含用户标识符(例如用户处于已开启的会话中)时,控制平面会使用线程池并行运行两个 Elasticsearch 查询:
- 针对策略索引的 percolator 查询(即第 3 和第 4 部分中描述的治理查找)。
- 对
user_purchases索引进行购买历史记录查询,通过term(user_id)过滤到特定用户,然后将当前搜索字符串与该用户的产品标题进行匹配。
这两个查询并发执行(互不等待),因此个性化查找不会显著增加治理管道的延迟。
在将当前搜索字符串与存储的产品标题进行匹配时,购买历史记录查询使用 Elasticsearch 的文本分析(提取词干、词汇切分)。这意味着,通过标准文本分析,搜索“曲奇”时,系统会匹配到过去购买的“布朗尼曲奇”,而无需进行精确的字符串匹配。
计算提升权重
并非所有过去的购买都应获得相同的提升。权重考虑了两种直观因素:购物者购买该产品的频率,以及最近购买时间。上周购买 15 次的产品,其信号强度远高于六个月前仅购买过一次的产品。权重计算采用频率的对数缩放(避免单一高频购买产品压倒其他一切产品),以及近因的指数衰减(使较早的购买随时间自然弱化)。
有关提升公式的数学细节,请参阅《无需 ML 后处理的 Elasticsearch 个性化搜索》。
如何成为查询的一部分
购买历史记录提升作为最外层的评分层被组合到查询中,包裹了第 3 和第 4 部分的治理策略筛选器和提升,以及任何业务信号提升,例如利润和热度(我们将在第 7 部分探讨)。这意味着由治理策略移除的产品不会因购买历史记录的提升而重新出现。治理 控制结果集;个性化 调整其中的排序。没有任何购买历史记录的产品不会被降权。它们的治理排名保持不变,但在其他条件相同的情况下,具有相关购买历史记录的产品会排在它们上面。

为什么每次搜索都要查询 Elasticsearch?
每次搜索时,购买历史记录都会从 Elasticsearch 中查询,而不是缓存在应用程序层中。这是一个经过深思熟虑的设计选择。由于查询通过 Elasticsearch 的文本分析管道匹配当前的搜索字符串与产品名称,系统受益于与产品搜索本身相同的词干提取、词汇切分和语言处理。缓存内存中的查找需要重新实施该分析,或接受更粗糙的匹配。
要了解为什么这种排序很重要,可以考虑一位以前购买过橙汁但现在正在搜索“橙子”的购物者。购买历史记录查询通过文本分析将“橙汁”与搜索词“橙子”进行匹配,并为该产品计算提升。但治理层已经将“橙子”限制在农产品类别中,完全过滤掉了橙汁。查询中包含针对橙汁的购买历史记录提升,但由于受控结果集中没有匹配的文档供其作用,因此该条件无效。购物者看到的是新鲜橙子,按相关性和个性化排序。治理机制依然有效。
性能成本极低:购买历史记录索引很小(一个用户的购买历史记录通常只有几十到几百个文档,而非数百万),并且查询与 Percolator 查找并行运行,因此不会延长关键路径。
无用户历史记录时搜索“spring water”的示例
如果未登录用户或从未购买过“spring water”的用户搜索,他们可能会看到类似以下的结果:

用户购买历史记录示例
另一方面,一位名叫 Carol 的用户的购物历史包含以下产品:

使用上述购买历史记录搜索“Spring water”的示例
如果 Carol 搜索“spring water”,她将看到反映她过去购买记录的个性化结果。从上面的购买历史来看,她购买了“Carbonated Spring Water”(绿色瓶子)约 40 次,最近一次购买是两天前。如果她搜索“spring water”,我们知道她喜欢这个产品,因此该产品会被提升。请注意,在非个性化结果中,Rubicon spring water 反而成为了第一个匹配项。

群组意识策略激活
个人购买历史记录对具有既定行为的回头客很有效。但许多购物者都是新用户、匿名用户,或在常规模式之外浏览。对于这些购物者来说,群组成员身份提供了一种不同类型的个性化服务,这种服务基于购物者的身份,而不是他们过去的行为。
一个素食者搜索“巧克力”时,应该看到素食巧克力排名更高。一个清真饮食者搜索“零食”时,应该突出显示清真认证的选项。一个注重健康的购物者搜索“酸奶”时,应该提升益生菌选项。
群组作即策略,而非产品标签
产品已带有其常规属性,包括 dietary_restrictions: ["vegan"] 或 dietary_restrictions: ["halal"] 等字段。问题在于,连接购物者群组与这些产品属性的逻辑应该放在哪里。
天真的做法是在应用层或搜索模板中硬编码该映射:如果用户是素食者,则在 dietary_restrictions: "vegan" 上添加提升。但这与第 1 部分中描述的应用层杂乱无章的情况相同,也会造成同样的运营摩擦:添加新群组或更改群组的含义都需要修改代码。
受治理控制平面将群组逻辑保留在策略引擎中。群组策略将两项内容关联起来:购物者的群组成员身份(例如“素食者”)和产品属性(例如 dietary_restrictions: “vegan”)。策略定义了连接:当素食者群组中的购物者进行搜索时,提升包含 dietary_restrictions “素食者”的产品。

由于群组逻辑存在于策略引擎而非应用代码中,这意味着:
- 添加新群组只需创建新策略,无需重新索引产品。
- 群组策略使用完整的规则引擎:它们可以添加过滤器、应用软提升、扩展同义词、更改检索策略,或执行策略可以采取的任何其他操作。
- 群组行为通过与其他所有策略相同的管理界面进行管理:运营人员可以通过第 2 部分中描述的“编写 → 测试 → 推广”工作流来创建、测试和推广群组策略。
素食群体政策示例
运营人员制定了一项具有以下特征的群组策略:
- 队列:
["vegan"]。 - 匹配标准:匹配任何查询(或特定产品类别)。
动作:对 dietary_restrictions: "vegan" 进行软提升,提升权重为 2。

群组激活的工作原理
每份策略文档都有一个 cohorts 字段。适用于所有购物者(无论群组如何)的通用策略可以将此字段留空,控制平面将在内部为其分配 "_all" 的值。群组特定策略存储其目标群组的名称,例如 ["vegan", "kosher", “sweet_tooth”]。
当搜索请求包含用户资料时,控制平面为 percolator 查询构建一个简单的 terms 筛选器:
这个单一筛选器包含所有通用策略以及用户特定群组的策略。_all 哨兵使其成为一个简洁的包含筛选器:无需 must_not 或 exists 查询来处理策略没有群组限制的情况。
然后 percolator 照常评估策略匹配。唯一的区别是候选策略集已被缩小到与该购物者的群组相关的那些策略。所有下游操作(级联转换、按字段冲突解决、消费短语跟踪)与第 3 部分和第 4 部分所描述的非个性化流程完全相同。
非素食(标准)用户搜索“巧克力”的结果
当非素食用户搜索巧克力时,搜索结果不会应用素食用户群体的推荐提升。他们经常在热门搜索结果中看到非素食巧克力,具体如下:

搜索“巧克力”时显示的素食者群组策略结果
当素食群组购物者搜索“巧克力”时,此策略会包含在 percolator 候选集中。它与之匹配,控制平面会对经过素食认证的巧克力进行软提升。该提升是乘法性的:素食巧克力排名更高,但非素食巧克力不会被完全排除,因为上述筛选器被定义为软性提升,我们在本系列的第 3 部分对此进行了详细描述。

不过,如果购物者明确搜索“好时牛奶巧克力”,素食提升效果仍然有效,但可能会被“好时牛奶巧克力”产品更强的文本相关性所抵消。

对于那些不在素食群组范围但搜索相同关键词的购物者而言,他们永远不会看到“素食群组”策略;该策略不在他们的候选集中。治理层完全相同,只是激活的策略集不同。
有购买历史记录的群组
一位拥有丰富购买历史记录的素食购物者,会同时获得针对素食者群组的策略激活以及基于其购买历史记录的产品提升。对于新用户或匿名购物者,仅隐含的群组成员资格即可提供有意义的个性化设置,无需任何行为数据(例如,一个匿名用户只搜索过素食产品,那么我们可以将其归类为素食群组成员)。一个在创建账户时自我标识为清真饮食者的购物者,在第一次搜索时就会立即获得清真定制的结果。

个性化层的组合方式
function_score层的嵌套顺序很重要。从最内到最外:
- 基本查询:带有命名查询(
fulltext_match、title_phrase_match)的关键词或语义匹配。 - 治理政策层:硬过滤作为
bool.filter条款,软提升作为function_score功能(第 3 和第 4 部分)。 - 业务信号提升:利润和热度提升 (我们将在第 7 部分探讨)。
- 购买历史记录提升:最外层的
function_score层。
这种排序方式可确保治理层控制结果集(显示什么内部),业务信号调整该集合内的排名(从零售商角度看什么显示在前面),而购买历史记录则根据个人行为进一步调整排序(从购物者的角度看什么显示在前面)。每一层以乘法方式包裹前一层,因此效果是叠加而非冲突。
这在运营层面上意味着什么
通过受治理的控制平面进行个性化,保留了第 1 和第 2 部分中描述的所有运营属性:
- 零部署变更。群组策略通过管理界面创建、测试和推广。新增饮食偏好群组或调整提升权重,无需修改代码,也不需要工程师介入。
- 可审计性。每个群组策略都是一个离散、版本化的文档。当运营人员询问“为什么这个用户的素食产品排名更高?”时,答案是一个具有特定优先级的特定策略,可以在调试面板中与该查询触发的所有其他策略一起看到。
- 冲突解决。群组策略第 3 部分中描述的相同按字段冲突解决机制。如果群组策略的类别提升与营销活动策略的类别覆盖冲突,冲突会由相同的优先级和策略框架确定性解决,无需特殊处理。
- 可衡量性。由于群组策略是离散且可以单独切换,它们对转化率、点击率和加购率的影响可以独立衡量,就像系统中任何其他策略一样。
本系列内容预告
下一篇文章将探讨受治理控制平面的另一个维度:如何通过策略按查询调整利润和热度提升,将经济优化转变为治理决策,而非静态配置。
参见第 7 部分:查询治理的经济优化:按查询的利润与热度提升
将受治理的电子商务搜索付诸实践
本文介绍的个性化模式(个人购买历史记录提升和群组感知策略激活)由 Elastic Services Engineering 设计并构建,是我们可复用的电子商务搜索加速器的一部分。这两种机制都与本系列中描述的受治理控制平面架构集成。请联系 Elastic Professional Services。
加入讨论
对搜索治理、检索策略或电子商务搜索架构有疑问?加入更广泛的 Elastic 社区讨论。




