Elasticsearch向量检索:让推荐系统真正“懂你所想”的工程实践
你有没有遇到过这样的问题:用户刚搜完“降噪耳机”,下一条推荐却是“苹果手机”——语义上似乎都和“科技产品”沾边,但实际体验却像被算法开了个玩笑?又或者,新上架的“骨传导游泳耳机”在类目体系里找不到归属,上线一周零曝光,运营同学急得直拍桌子?
这不是模型不够聪明,而是传统推荐架构的结构性瓶颈:语义理解与业务规则长期割裂,向量计算与文本检索分属两套系统,数据流绕来绕去,延迟越来越高,运维越来越重。
直到Elasticsearch 8.0把dense_vector和KNN搜索原生塞进Lucene底层——不是插件、不是桥接、不是API代理,而是像支持text字段一样自然地支持向量。这意味着:你不用再为向量单独搭一套FAISS集群,不用写一堆同步脚本保证Redis和ES之间的一致性,也不用在Spring Boot里硬塞一个gRPC客户端去调用向量服务。
它就在这里,和你的商品标题、用户标签、库存状态躺在同一个文档里,用同一个查询DSL被召回。
向量不再“特殊”:dense_vector是怎么在ES里活下来的?
很多人第一次看到dense_vector,下意识觉得:“这不就是个数组字段吗?”
但恰恰是这个“普通”,藏着最硬核的设计取舍。
它不走倒排索引,而走DocValues——这是性能锚点
传统text字段靠倒排索引实现关键词快速定位;而dense_vector被直接序列化为二进制,存进Lucene的DocValues结构——这是专为按文档随机访问优化的数据布局,也是聚合、排序、脚本字段的底层载体。换句话说,ES没把它当“要被搜索的词”,而是当“要被比对的特征”。
这就解释了为什么它支持与term、range、geo_distance等查询共存于同一bool上下文中:它们共享同一套文档加载路径,没有跨组件调度开销。
HNSW不是黑盒,而是一张可调优的“跳表地图”
ES默认启用HNSW(Hierarchical Navigable Small World)作为近似最近邻算法。你可以把它想象成一张多层城市地铁图:
- 最顶层只有几个枢纽站(比如“电子”“数码”“配件”),适合快速定位大方向;
- 往下一层站点变多,路径更细(如“音频设备”→“无线耳机”→“降噪款”);
- 底层则是完整站点网络,允许精确抵达。
这张图在索引刷新后异步构建,所以