限时福利领取


背景痛点

传统搜索引擎的排序算法(如TF-IDF、BM25)在电商、本地生活等场景下暴露明显短板。我曾负责一个外卖平台项目,最初仅按文本相关性和静态评分排序,结果出现:

  • 3公里外的网红店总排第一,实际配送时间超1小时
  • 新开业的高质量商户因历史数据不足长期沉底
  • 促销商品无法根据用户实时距离调整展示权重

这些问题的本质,是传统算法缺乏对动态空间特征和实时业务规则的处理能力。而AI+Geo混合方案能通过动态权重调整,将距离、价格、评分等多维度纳入实时计算。

技术方案选型

我们对比了三种主流实现方式:

  1. Elasticsearch Function Score
  2. 优势:原生支持,无需额外依赖
  3. 局限:复杂逻辑需写Painless脚本,调试困难
  4. 适用:中等复杂度规则(如基础距离衰减)

  5. 自定义排序插件

  6. 优势:Java开发,性能更好
  7. 局限:需重启集群,版本升级麻烦
  8. 适用:超大规模数据(如亿级POI)

  9. 向量检索

  10. 优势:适合多模态特征融合
  11. 局限:资源消耗大,延迟高
  12. 适用:图像/语义等非结构化特征

最终选择Function Score方案,因其在开发效率与性能间取得平衡。

核心实现细节

距离衰减函数实现

// 在Elasticsearch查询中使用Painless脚本
def originLat = params.origin.lat;
def originLon = params.origin.lon;
def maxDistance = params.maxDistance; // 单位:米

def distance = doc['location'].arcDistance(originLat, originLon);
if (distance > maxDistance) {
    return 0; // 超出范围直接过滤
}

// 高斯衰减公式:距中心1km时权重0.8,3km时0.2
def scale = 1000;
def offset = 0;
def decay = 0.2;
Math.exp(-0.5 * Math.pow((Math.max(0, distance - offset) / scale), 2)) / decay

多维度特征归一化

关键是要统一量纲:

  1. 价格维度:用Min-Max归一化到0-1区间

    normalized_price = (max_price - current_price) / (max_price - min_price)
  2. 评分维度:使用Wilson区间算法解决小样本问题

    # Python示例:计算评分下限
    def wilson_score(pos, n, z=1.96):
        phat = pos/n
        return (phat + z*z/(2*n) - z*math.sqrt((phat*(1-phat)+z*z/(4*n))/n))/(1+z*z/n)
  3. 距离维度:前文已实现高斯衰减

两阶段排序策略

  • 粗排阶段:先用bool查询过滤不符合基本条件的文档(如营业状态、品类匹配)
  • 精排阶段:对Top 100结果应用复合权重公式
    最终得分 = 0.4*文本相关分 + 0.3*距离分 + 0.2*评分 + 0.1*价格分

生产环境避坑指南

GeoHash精度问题

常见误区是直接使用GeoHash网格聚合,这会导致:

  • 边界上的点被错误分组
  • 不同精度的网格无法对比

解决方案:

// 改用GeoBoundingBox查询确保精准
QueryBuilder query = QueryBuilders.geoBoundingBoxQuery("location")
    .setCorners(topLeftLat, topLeftLon, bottomRightLat, bottomRightLon);

冷启动问题处理

新商户的解决方案:

  1. 人工设置初始权重(如新店加权15%)
  2. 基于品类平均分填充缺失值
  3. 在UI标注"新店尝鲜"标签

高并发优化

  • 使用Elasticsearch的请求缓存(size=0时自动启用)
  • 对非实时数据(如商户基础信息)做本地缓存
  • 热点区域查询结果预计算

性能验证数据

测试环境:3节点集群(16核64G SSD)

| 数据量 | 纯文本QPS | 混合模式QPS | TP99延迟增长 | |--------|-----------|-------------|--------------| | 100万 | 1200 | 950 | +18ms | | 1000万 | 800 | 650 | +35ms |

扩容建议:

  • 数据量超500万时,建议独立协调节点
  • 混合查询场景,每个分片不超过30GB

延伸思考

实际落地时我们还遇到两个哲学问题:

  1. 个性化与公平性:过度依赖距离可能导致优质偏远商户永远没曝光,最终我们引入『区域轮播』机制,每个地理区块保留20%展示位给非距离优先商户

  2. 位置授权拒绝:降级方案包括:

  3. 使用IP定位城市级别
  4. 默认展示城市热门榜单
  5. 二次引导时说明位置权限的价值

这套方案上线后,平台GMV提升27%,配送超时率下降41%。最大的教训是:距离衰减系数需要AB测试确定,我们最初设置的系数导致3km外订单骤减,后来通过动态调整系数解决了这个问题。

代码规范方面特别提醒:所有地理计算必须考虑地球曲率(用arcDistance而不是简单欧式距离),临界值检查需要处理浮点数精度问题(比如不要直接a==b,要用Math.abs(a-b)<1e-6)。

Logo

音视频技术社区,一个全球开发者共同探讨、分享、学习音视频技术的平台,加入我们,与全球开发者一起创造更加优秀的音视频产品!

更多推荐