当前位置: 首页 > news >正文

Spring AI 11 · 元数据过滤 FilterExpression

11 · 元数据过滤 FilterExpression

🎯 学完能做什么:用字符串表达式和 FilterExpressionBuilder 两种方式,按 metadata 精确圈定检索范围,实现多租户、分类、时间过滤。
⏱️ 预计耗时:40 分钟(含动手)
🔗 依赖前置:第 09、10 章 + pgvector 文档14(带过滤的向量检索)
🧩 难度:🟡

一句话:向量检索负责「找最像的」,元数据过滤负责「限定在哪些里面找」;两者结合才能做出多租户、分权限、按分类的生产级检索。

1. 为什么需要过滤

只靠相似度会检索到「全库最像的」,但业务上你往往只想在特定范围内找:

只查 租户 1001 的资料 只查 分类=售后 的资料 只查 2025 年之后更新的资料

这些「范围」信息就存在灌库时写的metadata(第 09 章)里,过滤就是对 metadata 下条件。

2. 方式一:字符串表达式(直观)

List<Document>hits=vectorStore.similaritySearch(SearchRequest.builder().query("退货政策").topK(3).filterExpression("category == '售后' && tenantId == '1001'").build());

支持的运算符:

运算符含义示例
==!=等于 / 不等于category == '售后'
>>=<<=比较year >= 2025
innin在/不在集合category in ['售后','物流']
&&||与 / 或a == 1 && b == 2
NOT取反NOT (status == 'draft')

3. 方式二:FilterExpressionBuilder(类型安全)

代码里动态拼条件时更安全、不易写错:

FilterExpressionBuilderb=newFilterExpressionBuilder();Filter.Expressionexpr=b.and(b.eq("tenantId","1001"),b.in("category","售后","物流")).build();List<Document>hits=vectorStore.similaritySearch(SearchRequest.builder().query("退货").topK(3).filterExpression(expr).build());

常用构建方法:eq / ne / gt / gte / lt / lte / in / nin / and / or / not,与字符串运算符一一对应。

4. 典型场景

多租户隔离(SaaS 必备)

// 每个请求都强制带上当前租户,避免串数据StringtenantId=currentTenant();b.eq("tenantId",tenantId).build();

🔐 安全要点:多租户过滤应在服务端强制注入,绝不能让前端传、也不能漏——否则会跨租户泄露数据。

按分类 + 时间

b.and(b.eq("category","公告"),b.gte("year",2025)).build();

动态拼接(有就加,没有不加)

FilterExpressionBuilderb=newFilterExpressionBuilder();List<Filter.Expression>parts=newArrayList<>();parts.add(b.eq("tenantId",tenantId).build());if(category!=null)parts.add(b.eq("category",category).build());// 用 and 逐个合并 parts ...

5. 过滤 + 相似度的执行关系

similaritySearch: 1) 先按 filterExpression 圈定候选(metadata 命中的行) 2) 在候选里按向量相似度排序,取 topK / 过阈值

⚠️ 性能提醒:过滤条件很「窄」(命中极少)时,纯向量索引可能出现召回不足。这在 pgvector 文档21、22(带过滤检索的召回塌陷、迭代扫描)有系统讲解,生产必读。

6. 让过滤生效的前提:metadata 要灌对

过滤能不能用,取决于灌库时有没有写对应字段(回顾第 09 章):

// 灌库时写入可过滤字段vectorStore.add(List.of(newDocument(content,Map.of("tenantId","1001","category","售后","year",2026))));

🔑 「先想清楚要按什么筛,再决定 metadata 放什么」——过滤能力是灌库阶段就注定的。

7. 常见坑

现象原因
过滤后结果为空metadata 里根本没这个字段/值;或类型不符(数字写成字符串)
过滤没生效字段名拼错,或值大小写/类型不匹配
窄过滤召回很差命中太少 + ANN 索引特性,见 pgvector 21/22
跨租户看到别人数据服务端没强制注入租户过滤

8. 一句话总结

元数据过滤用filterExpression(字符串或 Builder),在相似检索前圈定范围,是多租户、分类、时间等生产场景的基础;能不能过滤取决于灌库时 metadata 写得对不对。


🎉第二阶段完成!你现在掌握了:生成向量、配置 pgvector、写入(含幂等)、相似检索、元数据过滤——RAG 的数据层已经打通。

➡️ 下一阶段(第 12–15 章)进入文档处理 ETL:把真实的 PDF/Markdown 读进来、分块、富化 metadata、批量灌库,让知识库有真正的内容。

http://www.cnnetsun.cn/news/4207009.html

相关文章:

  • Spring Boot在线问诊系统设计:多语言、弱网与医疗协同的实战挑战
  • Godot 4 实战:从零构建像素风农场模拟游戏核心系统
  • LangChain Agent集成MCP协议:实现AI工具即插即用的标准化方案
  • 拼多多算法团队招聘:推荐、搜索与广告算法核心技术解析
  • MLLM引导语义校正:用大模型优化AI视频生成逻辑
  • 2026年采购智能鞋头后跟定型机,选哪家工厂性价比更高?
  • 山东高考志愿填报机构口碑与适用分析
  • 抖音批量下载工具实战:主页合集一键归档
  • C#图像高速存储落盘:提高图像从内存中落盘存储到硬盘速度的几个方法
  • 前端面试实战:技术深度与表达策略
  • AssetRipper完整教程:免费开源的Unity资产提取工具,5分钟从.assets文件里找回整个游戏
  • FlywayGuard:IDEA插件解决Flyway SQL冲突
  • 本地AI相册实战:基于ONNX与Tesseract的私有化图片管理方案
  • 2026之后,通用咨询公司难再做B2B全案
  • 吴恩达AI Agent技能开发教程:从工具调用到实战部署全解析
  • Substance 3D Designer 风格化木板材质制作全流程解析
  • RocketMQ事务消息原理与面试深度解析
  • AI智能体本地部署与实战:从环境搭建到API集成全流程
  • 2026福州工程建筑材料检测排名 TOP5 CMA 资质提供钢材检测、水泥检测、砂石检测 全覆盖联系方式推荐.txt
  • Kubernetes 靠什么活下来?拆解 K8s 集群可靠性设计的 5 个核心机制
  • GMK冷门键帽团购全解析:秘密项目风险与价值评估指南
  • DeepSeek-TUI:终端AI编程助手,重塑开发工作流
  • 2026年前端面试:从八股文到实战理解的转变
  • Carla仿真系列:10_Carla 双目障碍物测距,视差图还原真实距离
  • 第18章:FastAPI异步数据库访问与连接池
  • 从被动审核到主动风控:构建下一代视频内容安全体系
  • 简历优化全攻略:提升求职成功率的实用技巧
  • Java全栈开发工程师面试核心要点与实战策略
  • 腾讯云直播音频审核实战:三种开启方式与避坑指南
  • 2026固原工程建筑材料检测排名 TOP5 CMA 资质提供钢材检测、水泥检测、砂石检测 全覆盖联系方式推荐.txt