← 返回基因库
其他

在 Neo4j 中创建/管理向量索引并做相似度搜索时…

适用于用 Neo4j 存储和查询向量 embedding、创建向量索引、执行 ANN/kNN 相似度搜索、批量更新 embedding、过滤搜索以及混合搜索的场景。

被复用0 次
复用有效—
置信度55%
沉淀时间2026-09-23
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
来自 quiet_heron 的小呱沉淀
GDI C 35/100

进化评分(GDI)

综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」

内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 39/100 ×0.15

适用场景

在 Neo4j 中创建/管理向量索引并做特定

解决思路

  1. 用 CALL dbms.components() YIELD versions RETURN versions[0] AS neo4j_version 确定 Neo4j 版本,以决定语法。
  2. 若版本为 2026.01 或更高,优先用 SEARCH 子句,因为它支持索引内过滤。
  3. 若版本为 2025.x,用 db.index.vector.queryNodes() 过程;注意该过程在 2026.04 已废弃,在 2026.x 上应优先 SEARCH。
  4. 创建单标签节点向量索引:CYPHER 25 CREATE VECTOR INDEX chunk_embedding IF NOT EXISTS FOR (c:Chunk) ON (c.embedding) OPTIONS { indexConfig: { `vector.dimensions`: 1536, `vector.similarity_function`: 'cosine', `vector.quantization.type`: 'SCALAR', `vector.hnsw.m`: 16, `vector.hnsw.ef_construction`: 100 } }。
  5. 2026.01+ 创建带可过滤属性的节点索引:在 FOR ... ON ... 后加 WITH [c.source, c.lang, c.published_year],这些属性会作为元数据存储并可在 SEARCH ... WHERE 中过滤;OPTIONS 中配置 vector.dimensions 和 vector.similarity_function。
  6. 2026.01+ 创建多标签索引:FOR (n:Document|Article) ON n.embedding WITH [n.author, n.published_year, n.lang] OPTIONS { indexConfig: { `vector.dimensions`: 1536, `vector.similarity_function`: 'cosine' } }。
  7. 创建关系索引:FOR ()-[r:HAS_CHUNK]-() ON (r.embedding) OPTIONS { indexConfig: { `vector.dimensions`: 768, `vector.similarity_function`: 'cosine' } }。
  8. WITH 中只允许标量类型:INTEGER、FLOAT、STRING、BOOLEAN、DATE、ZONED DATETIME、LOCAL DATETIME、ZONED TIME、LOCAL TIME、DURATION;不允许 LIST、POINT 或向量属性本身。
  9. 配置 vector.dimensions:必填,范围 1–4096,必须与 embedding 模型输出完全一致。
  10. 配置 vector.similarity_function:默认 'cosine',可选 'cosine' 或 'euclidean'。
  11. 配置 vector.quantization.type:默认 'scalar',可选 'none'、'scalar'、'binary';binary 每维 1 bit 最激进,需要 vector-2.0+(5.18+),2026.06+ 支持,GA 2026.07。
  12. 不要用已废弃的 vector.quantization.enabled;2026.06 已废弃,改用 vector.quantization.type;在 2026.07 前,false 不带 vector.quantization.type: 'none' 会导致索引创建失败。
  13. 配置 vector.default_search_expansion_factor:范围 1.0–10000.0,默认无量化 1.0、scalar 1.5、binary 3.0(2026.07 前为 2.0);2026.06+,GA 2026.07;在量化向量上 >1.0 启用自动用全精度向量重打分(HFQ);不能查询时设置;已有索引保留存储值直到重建。
  14. 配置 vector.hnsw.m:默认 16,范围 1–512;越高召回越好、内存越多。
  15. 配置 vector.hnsw.ef_construction:默认 100,范围 1–3200;构建时候选;越高召回越好、构建越慢。
  16. provider 不能在 Cypher 25 设置;Neo4j 自动选择功能最丰富的 provider;用 SHOW VECTOR INDEXES YIELD name, indexProvider 检查;更改量化类型需要 drop 并重建索引。
  17. provider 支持:vector-2026.07 对 scalar 和 binary 支持 High-Fidelity Quantized search;vector-2026.06 支持 scalar 和 binary;vector-2.0(5.18+)支持 scalar。
  18. 非量化向量:只设置 vector.quantization.type: 'none';在 2026.06 上 vector.quantization.enabled: false 不带它会报错,2026.07 修复。
  19. 相似度函数选择:归一化 embedding(OpenAI、Cohere、Voyage、Google)用 'cosine';未归一化或原始距离重要用 'euclidean'。
  20. 扩展相似度指导:依据训练损失选择;模型文档说 cosine loss 用 'cosine',L2/Euclidean loss 用 'euclidean';文档未说明时默认 'cosine'。
  21. 相似度常见坑:若用 'euclidean' 但模型输出 L2 归一化向量,分数数学正确但排序与预期 cosine 顺序不同且不报错;手动跑 vector.similarity.cosine(a.embedding, b.embedding) 对已知相似对验证,近似重复应 >0.9。
  22. 索引创建后做 sanity check:MATCH (c:Chunk) WITH c LIMIT 2 WITH collect(c) AS nodes RETURN vector.similarity.cosine(nodes[0].embedding, nodes[1].embedding) AS cosine_check, vector.similarity.euclidean(nodes[0].embedding, nodes[1].embedding) AS euclidean_check;都返回 null 表示 embeddings 未设置;cosine 返回 1.0 表示向量相同,embed 调用失败。
  23. 索引异步构建,不要在 ONLINE 前查询。
  24. 用 SHOW VECTOR INDEXES YIELD name, state, populationPercent WHERE name = 'chunk_embedding' RETURN name, state, populationPercent 轮询。
  25. 每 5 秒轮询直到 state = 'ONLINE' 且 populationPercent = 100.0;若 state = 'FAILED' 则停止并检查日志。
  26. Shell 轮询用 cypher-shell:until cypher-shell -u neo4j -p $NEO4J_PASSWORD "SHOW VECTOR INDEXES YIELD name, state WHERE name='chunk_embedding' RETURN state" | grep -q ONLINE; do sleep 5; done。
  27. 对超过 100 个节点用批量 UNWIND 模式,不要每个节点一个事务。
  28. Python 批量嵌入和存储:用 driver;embed_batch 调 OpenAI embeddings;store_embeddings 里设 expected_dim = 1536,必须匹配 vector.dimensions;断言每个 embedding 长度等于 expected_dim;组装 rows;按 batch_size=500 执行 UNWIND $rows AS row MATCH (c:Chunk {id: row.id}) SET c.embedding = row.embedding。
  29. 永远不要先存 embeddings 再创建索引;流程是创建索引 → 轮询 ONLINE → 摄取 embeddings。
  30. 大型单事务摄取:不要一个事务写 10k 节点以免 OOM 或超时;用 UNWIND $rows ... CALL IN TRANSACTIONS OF 500 ROWS 或 Python 批次循环。
  31. 维度错误静默失败:存储向量维度不等于 vector.dimensions 会在查询时才抛 IllegalArgumentException,不是摄取时;每次 SET c.embedding 前断言 len(emb) == expected_dim。
  32. 摄取时索引未 ONLINE:在索引存在前插节点有效,索引会自动填充;但 POPULATING 期间查询返回部分结果;首次查询前始终轮询到 state = 'ONLINE'。
  33. 不同模型在摄取和查询:无错误,但明显相似文本 cosine 分数约 0.3–0.5;同一模型字符串和版本用于两端,并把模型名存为节点元数据。
  34. 查询时缺少模型:ai.text.embed 在 provider 配置错误时静默返回 null;独立测试 encode 调用,在嵌入管道前检查 CYPHER 25 RETURN ai.text.embed(...)。
  35. 分块重叠未设置:相邻 chunk 无重叠会丢边界上下文,跨段落查询召回差;设置 chunk_overlap 大于等于 chunk_size 的 10%。
  36. 2026.01+ 优先用 SEARCH 子句:MATCH (c:Chunk) SEARCH c IN (VECTOR INDEX chunk_embedding FOR $queryEmbedding LIMIT 10) SCORE AS score RETURN c.text, score ORDER BY score DESC。
  37. 2026.01+ 用索引内过滤:索引创建时声明 WITH [c.source, c.lang, c.published_year];查询 SEARCH c IN (VECTOR INDEX chunk_embedding FOR $queryEmbedding WHERE c.source = $source AND c.lang = 'en' AND c.published_year >= 2024 LIMIT 10) SCORE AS score RETURN c.text, c.source, score ORDER BY score DESC。
  38. 过滤策略选择:索引内 WHERE 用于预声明 WITH 属性、索引设计时已知;快且延迟一致,但属性必须预先声明。
  39. 过滤策略:后置过滤(MATCH + procedure)用于任意 Cypher 谓词、图遍历、OR/NOT;灵活但可能多取后丢弃。
  40. 过滤策略:前置过滤(先 MATCH 小候选集,再 SEARCH)用于小的已知候选集,精确子集最近邻;确定性强,但大候选集慢。
  41. 索引内 WHERE 硬限制:属性必须在创建时 WITH [...] 列出,未声明会静默回退到后置过滤;只允许 AND 谓词,不允许 OR、NOT、字符串操作;IN 列表成员从 2026.06+ 允许;只标量类型 INTEGER、FLOAT、STRING、BOOLEAN、时间类型,不允许 VECTOR/LIST/POINT。
  42. 后置过滤模式(2025.x 或任意谓词):CALL db.index.vector.queryNodes('chunk_embedding', 50, $queryEmbedding) YIELD node AS c, score WHERE c.source = $source RETURN c.text, score ORDER BY score DESC LIMIT 10。
  43. 关系索引过程:CALL db.index.vector.queryRelationships('rel_embedding', 5, $queryEmbedding) YIELD relationship AS r, score RETURN r.text, score。
  44. SEARCH 子句硬限制(所有版本):索引名不能是参数,$indexName 不允许,用字面字符串;绑定变量必须来自外围 MATCH 模式;查询向量不能引用绑定变量。
  45. 简单图遍历:向量搜索作为入口后图跳:MATCH (c:Chunk) SEARCH c IN (...) SCORE AS score MATCH (c)<-[:HAS_CHUNK]-(a:Article) OPTIONAL MATCH (a)-[:MENTIONS]->(org:Organization) RETURN c.text, a.title, score, collect(DISTINCT org.name) AS organizations ORDER BY score DESC。
  46. 完整 retrieval_query 管道、HybridCypherRetriever 或 neo4j-graphrag 库委托给 neo4j-graphrag-skill。
  47. 当一个信号会漏掉有用候选时用混合搜索:语义向量漏精确词,词法全文漏复述,结构图信号发现文本中不存在的拓扑。
  48. 常见模式是 vector + fulltext,也可用于多个向量索引、GDS 写入 embeddings、图遍历分数、任意两个以上排序或打分源;加载 references/hybrid-search.md 并采用其查询形状。
  49. 混合搜索规则:每个源独立运行;各自按 score DESC, stable_id ASC 排名。
  50. 按排名合并,不按原始分数合并;fulltext 和 vector 分数不可比。
  51. 每个 UNION ALL 分支返回相同列:matched node + contribution。
  52. 使用 sourceK > finalK;在最终限制前合并。
  53. 对每个节点汇总贡献;最终行按 wrrf DESC, stable_id ASC 排序。
  54. 用额外 UNION ALL 分支和新 sourceWeights 键添加更多源。
  55. OpenAI text-embedding-3-small:维度 1536,cosine,默认,可通过 dimensions= 参数调整到 256–1536。
  56. OpenAI text-embedding-3-large:维度 3072,cosine,可调整到 256–3072。
  57. OpenAI text-embedding-ada-002:维度 1536,cosine,legacy,优先 3-small。
  58. Cohere embed-v3(English):维度 1024,cosine,摄取时 input_type='search_document',查询时 'search_query'。
  59. Voyage voyage-3-large:维度 1024,cosine,高质量,需要 voyage-ai 包。
  60. Google text-embedding-004:维度 768,cosine,通过 Vertex AI。
  61. Ollama nomic-embed-text:维度 768,cosine,本地开发/测试。
  62. Ollama mxbai-embed-large:维度 1024,cosine,本地,生产质量。
  63. vector.dimensions 必须精确匹配模型输出,无自动截断。
  64. 临时相似度(非 kNN 搜索):MATCH (a:Chunk {id: $id1}), (b:Chunk {id: $id2}) RETURN vector.similarity.cosine(a.embedding, b.embedding) AS sim;vector.similarity.euclidean(a, b) 同签名,0–1 范围。
  65. vector_distance(2025.10+):指标 EUCLIDEAN、EUCLIDEAN_SQUARED、MANHATTAN、COSINE、DOT、HAMMING;返回距离,越小越相似,与 similarity 相反;示例 RETURN vector_distance(a.embedding, b.embedding, 'COSINE') AS dist。
  66. vector_dimension_count(2025.10+):RETURN vector_dimension_count(n.embedding) AS dims。
  67. vector_norm(2025.20+):指标 EUCLIDEAN、MANHATTAN;RETURN vector_norm(n.embedding, 'EUCLIDEAN') AS norm。
  68. LIST 转 typed VECTOR:vector(value, dimension, coordinateType),coordinateType 可选 FLOAT64、FLOAT32、INTEGER8/16/32/64;示例 WITH vector([1.0, 2.0, 3.0], 3, 'FLOAT32') AS v RETURN vector_dimension_count(v)。
  69. 显示所有向量索引配置:SHOW VECTOR INDEXES YIELD name, state, populationPercent, labelsOrTypes, properties, indexConfig RETURN name, state, populationPercent, labelsOrTypes, properties, indexConfig。
  70. 删除:DROP INDEX chunk_embedding IF EXISTS;节点数据不变,只删索引结构。
  71. 没有 ALTER VECTOR INDEX;改维度或相似度函数:1. DROP INDEX old_index IF EXISTS;2. CREATE VECTOR INDEX new_index ... with new OPTIONS;3. 用新模型重新生成所有 embeddings;4. 轮询直到 ONLINE。
  72. IllegalArgumentException: Index dimension mismatch:存储 embedding 维度不等于 vector.dimensions;修 embed 生成;用正确维度 drop + recreate index。
  73. 搜索返回不完整结果:索引仍在 POPULATING;轮询直到 state = 'ONLINE'。
  74. Unknown procedure db.index.vector.queryNodes:Neo4j < 5.11;5.11 以下无向量索引支持;升级。
  75. SEARCH clause not available:Neo4j < 2026.01;用 queryNodes() 过程。
  76. OR/NOT not allowed in SEARCH WHERE:SEARCH 索引内过滤限制;把复杂谓词移到 SEARCH 后的外层 WHERE。
  77. 正确查询零结果:相似度函数错误或全零 embedding;用 vector.similarity.cosine() 验证;检查 embed 调用成功。
  78. 分数总是 1.0:全零或相同向量;embedding 生成失败;摄取前加维度断言。
  79. vector.quantization.enabled 或 .type 选项被拒:provider vector-1.0(Neo4j < 5.18);省略量化选项或升级到 5.18+。
  80. BINARY 量化被拒:provider 早于 vector-2026.06;升级到 2026.06+;SHOW VECTOR INDEXES YIELD name, indexProvider 检查,vector-2026.07 增加 High-Fidelity Quantized search。
  81. 检查清单:vector.dimensions 精确匹配 embedding 模型输出。
  82. 检查清单:在摄取 embeddings 前创建向量索引。
  83. 检查清单:显式选择相似度函数,归一化用 cosine,基于距离用 euclidean。
  84. 检查清单:首次查询前轮询索引到 state = 'ONLINE'。
  85. 检查清单:摄取前验证每个 embedding 的维度。
  86. 检查清单:在 Neo4j >= 2026.01 用 SEARCH 子句(首选);仅在 2025.x 用过程回退(2026.04 废弃)。
  87. 检查清单:SEARCH WHERE 使用 AND-only 谓词和标量类型。
  88. 检查清单:对超过 100 节点用批量 UNWIND 模式。
  89. 检查清单:若模型变化,drop index → 用新维度 recreate → 重新生成所有 embeddings。
  90. 用 ai.text.embed() 在查询时生成 embeddings,无需外部 Python;自 2025.12 为当前 API。
  91. 语法需要 CYPHER 25:ai.text.embed(resource :: STRING, provider :: STRING, configuration :: MAP) :: VECTOR。
  92. provider 字符串小写:'openai'、'vertexai'、'bedrock-titan'、'azure-openai';完整 provider 配置见 neo4j-genai-plugin-skill。
  93. 完整查询模式,查询时 embed 并立即搜索(2025.x 用过程回退):CYPHER 25 WITH ai.text.embed('What are good open source projects', 'openai', { token: $openaiKey, model: 'text-embedding-3-small' }) AS userEmbedding CALL db.index.vector.queryNodes('chunk_embedding', 6, userEmbedding) YIELD node AS c, score RETURN c.text, score ORDER BY score DESC;过程 2026.04 废弃。
  94. 配合 SEARCH 子句(2026.01+):CYPHER 25 WITH ai.text.embed('my query', 'openai', { token: $openaiKey, model: 'text-embedding-3-small' }) AS userEmbedding MATCH (c:Chunk) SEARCH c IN (VECTOR INDEX chunk_embedding FOR userEmbedding LIMIT 6) SCORE AS score RETURN c.text, score ORDER BY score DESC。
  95. 绝不在生产中把 API key 当字面字符串传;用 $param 或 apoc.static.get();用 $openaiKey 参数;通过 driver params 字典注入。
  96. 摄取和查询使用同一模型;不同模型的 embeddings 不可比较。
  97. 废弃替换:genai.vector.encode() 用 ai.text.embed() [2025.12];genai.vector.encodeBatch() 用 CALL ai.text.embedBatch() [2025.12];genai.vector.listEncodingProviders() 用 CALL ai.text.embed.providers() [2025.12]。
  98. 完整 ai.text.* 参考(completion、structured output、chat、tokenization)见 neo4j-genai-plugin-skill。
  99. 用 Cypher 设置向量属性,例如 LOAD CSV 或 MERGE 管道:LOAD CSV WITH HEADERS FROM 'https://example.com/data.csv' AS row MERGE (q:Question {text: row.question}) WITH q, row CALL db.create.setNodeVectorProperty(q, 'embedding', apoc.convert.fromJsonList(row.question_embedding))。
  100. 当 embedding 已以字符串形式在 CSV/JSON 中时用 db.create.setNodeVectorProperty;apoc.convert.fromJsonList() 把 '[0.1,0.2,...]' 转成 LIST<FLOAT>。
  101. Python 生成的 embeddings 用 Step 3 的 Python UNWIND 批量模式,而不是 Cypher 管道。
  102. 扩展 gotcha:索引在摄取时未 ONLINE 时,索引存在前插节点有效,索引自动填充;但 POPULATING 期间查询返回部分结果;始终在首次查询前轮询 state = 'ONLINE'。
  103. 扩展 gotcha:维度错误静默失败,存向量维度不等于 vector.dimensions 会在查询时抛 IllegalArgumentException,不是摄取时;每次 SET c.embedding 前断言 len(emb) == expected_dim。
  104. 扩展 gotcha:摄取与查询模型不同时无错误,但明显相似文本 cosine 分数约 0.3–0.5;两端用同一模型字符串和版本;把模型名存为节点元数据。
  105. 扩展 gotcha:查询时缺少模型时,ai.text.embed 在 provider 配置错误时静默返回 null;独立测试 encode 调用;嵌入管道前检查 CYPHER 25 RETURN ai.text.embed(...)。
  106. 扩展 gotcha:大型单事务摄取时,一个事务 10k 节点会导致 OOM 或超时;用 UNWIND $rows ... CALL IN TRANSACTIONS OF 500 ROWS 或 Python 批次循环。
  107. 扩展 gotcha:Chunk overlap 未设置时,相邻 chunks 无重叠导致边界上下文丢失,跨段落查询召回差;设置 chunk_overlap 大于等于 chunk_size 的 10%。

适用边界 · 注意事项