
本文详解如何使用 Pinecone Python SDK,通过 filter 参数按 hash_code 等自定义元数据字段精准筛选已存在的向量,避免重复插入相同 PDF 文档,提升向量库去重效率与可靠性。
本文详解如何使用 pinecone python sdk,通过 `filter` 参数按 `hash_code` 等自定义元数据字段精准筛选已存在的向量,避免重复插入相同 pdf 文档,提升向量库去重效率与可靠性。
在 Pinecone 中,直接通过 fetch(ids=...) 查找向量仅适用于你已知其向量 ID 的场景;而你的目标是根据元数据中的 hash_code 字段(非向量 ID)判断文档是否已存在——此时必须使用 metadata filtering + query 或更推荐的 query 配合 filter 参数(Pinecone v3+ 支持),而非 fetch 或无条件全量扫描。
✅ 正确做法:使用 filter 进行元数据精确匹配
Pinecone 的 query() 方法支持结构化元数据过滤(需索引启用 metadata search,且字段类型兼容)。假设你已将 hash_code 作为字符串存入每个向量的 metadata,以下为高效、可扩展的实现:
import pinecone
def filter_existing_docs(index_name: str, docs: list) -> list:
"""
根据文档 metadata 中的 'hash_code' 过滤出尚未存入 Pinecone 的新文档
Args:
index_name: Pinecone 索引名称
docs: LangChain Document 列表或含 .metadata['hash_code'] 的对象列表
Returns:
未重复的文档列表(即 hash_code 在索引中不存在的文档)
"""
# 初始化索引(确保已初始化 client)
index = pinecone.Index(index_name)
# 提取待检查的 hash_codes
target_hashes = [doc.metadata.get("hash_code") for doc in docs]
# 去重并过滤空值
target_hashes = list(set(filter(None, target_hashes)))
if not target_hashes:
return docs # 无有效 hash,全部保留
# 批量查询:对每个 hash_code 单独执行 filter 查询(安全可靠,避免 OR 逻辑复杂性)
existing_hashes = set()
for h in target_hashes:
try:
# 使用 filter 精确匹配元数据字段(注意:hash_code 必须是字符串,且已正确写入)
res = index.query(
vector=[0.0] * 1536, # 占位向量(必须提供,但不参与相似度计算)
top_k=1,
include_metadata=True,
filter={"hash_code": {"$eq": h}} # ✅ 关键:按元数据字段精确过滤
)
if res["matches"]:
existing_hashes.add(h)
except Exception as e:
print(f"Warning: Failed to query hash '{h}': {e}")
continue
# 过滤掉已存在的文档
filtered_docs = [
doc for doc in docs
if doc.metadata.get("hash_code") not in existing_hashes
]
print(f"✅ Found {len(existing_hashes)} existing hash(es). "
f"Filtered {len(docs) - len(filtered_docs)} duplicate(s).")
return filtered_docs
⚠️ 注意事项与最佳实践
-
vector参数不可省略:即使只做过滤,query()仍要求传入一个与索引维度一致的占位向量(如[0.0]*dim)。Pinecone 不支持纯 metadata-only scan。 -
filter语法严格:确保hash_code字段在写入时为字符串类型(非 bytes 或 int),且$eq匹配区分大小写和全字符。 -
性能优化建议:
- 若待查 hash 数量极大(>100),可改用
batch_query(Pinecone 3.4.0+)或分批处理,避免请求超时; - 确保
hash_code字段已建立索引(Pinecone 默认对所有 string 元数据字段索引,无需额外操作);
- 若待查 hash 数量极大(>100),可改用
-
避免全量扫描:不要使用
top_k=10000+include_metadata=True获取全部向量再本地过滤——该方式成本高、易超限、不可扩展。 -
写入时验证:插入新向量前,务必确认
metadata={"hash_code": "xxx", ...}已正确传入upsert(),否则filter将永远匹配不到。
✅ 总结
基于元数据去重的核心是:用 filter={"hash_code": {"$eq": h}} 替代 ids= 或无条件 query。该方法语义清晰、结果确定、符合 Pinecone 最佳实践。配合占位向量和批量循环,即可稳健支撑 PDF 文档级去重流程,确保向量库内容唯一、准确、可维护。











