Neo4j:优化的 Cypher 查询工程 - Openclaw Skills

作者:互联网

2026-03-30

AI教程

什么是 Neo4j?

Neo4j 技能是一个专门的技术模块,旨在弥合复杂图数据需求与高性能 Cypher 执行之间的差距。它提供了一个强大的框架来管理节点和关系,同时避免了无界路径爆炸和意外笛卡尔积等常见陷阱。通过将此模块集成到 Openclaw Skills 中,开发人员可以自动创建复杂的图模式,并确保其数据库交互保持可扩展且安全。

下载入口:https://github.com/openclaw/skills/tree/main/skills/ivangdavila/neo4j

安装与下载

1. ClawHub CLI

从源直接安装技能的最快方式。

npx clawhub@latest install neo4j

2. 手动安装

将技能文件夹复制到以下位置之一

全局模式 ~/.openclaw/skills/ 工作区 /skills/

优先级:工作区 > 本地 > 内置

3. 提示词安装

将此提示词复制到 OpenClaw 即可自动安装。

请帮我使用 Clawhub 安装 neo4j。如果尚未安装 Clawhub,请先安装(npm i -g clawhub)。

Neo4j 应用场景

  • 为节点和关系实现安全的 upsert 模式,以防止数据重复。
  • 通过自动索引和唯一约束管理优化图搜索性能。
  • 使用内存高效的批量事务执行大规模数据修改和删除。
  • 构建带有边界变量长度路径的复杂遍历逻辑,以防止系统崩溃。
Neo4j 工作原理
  1. 该技能分析图架构并识别操作所需的特定节点标签和关系类型。
  2. 它生成优化的 Cypher 模式,优先考虑索引属性查找并防止全标签扫描。
  3. 对于多步操作,它使用 WITH 子句管理变量范围,以确保数据在查询段之间正确流动。
  4. 它将数据修改包装在事务块或批处理命令中,以维护数据库的稳定性和性能。

Neo4j 配置指南

要利用此技能,您必须在系统上安装 Neo4j 数据库或 Cypher shell 工具。

# 在 macOS 上使用 Homebrew 安装 Neo4j
brew install neo4j

# 或者,使用 Docker 部署 Neo4j
docker run -d --name neo4j_db -p 7474:7474 -p 7687:7687 neo4j

Neo4j 数据架构与分类体系

数据元素 描述
节点 带有 ID 属性唯一约束的有标签实体(例如 :User, :Post)。
关系 具有特定类型(例如 :KNOWS)的节点之间的定向连接。
索引 用于加速 WHERE 子句过滤的全文本、范围和点索引。
参数 用于防止查询注入和计划缓存的结构化映射。
name: Neo4j
description: Write Cypher queries with proper patterns for merging, traversal, and performance.
metadata: {"clawdbot":{"emoji":"???","requires":{"anyBins":["cypher-shell","neo4j"]},"os":["linux","darwin","win32"]}}

MERGE Trap

  • MERGE matches the FULL pattern—MERGE (a)-[:KNOWS]->(b) creates duplicates if relationship missing
  • Safe upsert: merge nodes separately, then merge relationship
  • Use ON CREATE SET and ON MATCH SET for conditional properties—without these, nothing updates on match
  • For simple node upsert: MERGE (n:User {id: $id}) with unique constraint on id

Indexes

  • No index on property = full label scan—always index properties used in WHERE
  • Unique constraint auto-creates index—prefer constraint over plain index when applicable
  • Check plan with EXPLAIN before production—look for "NodeByLabelScan" without filter pushdown
  • Text search needs full-text index: CREATE FULLTEXT INDEX FOR (n:Post) ON EACH [n.title, n.body]

Variable-Length Paths

  • Unbounded [*] explodes on connected graphs—always set upper bound [*1..5]
  • [*0..] includes start node—usually unintended, start from [*1..]
  • shortestPath() returns one path only—use allShortestPaths() for all equally short paths
  • Filter inside path is expensive: [r:KNOWS* WHERE r.active] scans then filters—consider data model change

Cartesian Product

  • Two disconnected patterns multiply: MATCH (a:User), (b:Product) returns rows × rows
  • Connect patterns or split with WITH—unintended cartesian kills performance
  • Same variable in two patterns = implicit join, no cartesian
  • PROFILE query shows "CartesianProduct" operator when it happens

WITH Scope Reset

  • Only variables in WITH carry forward—MATCH (a)--(b) WITH a loses b
  • Aggregation forces WITH: MATCH (u:User) WITH u.country AS c, count(*) AS n
  • Common mistake: filtering after aggregation requires second WITH
  • Pagination: WITH n ORDER BY n.created SKIP 10 LIMIT 10

NULL Propagation

  • OPTIONAL MATCH returns NULL for missing patterns—NULLs propagate through expressions
  • WHERE after OPTIONAL MATCH filters out NULLs—use COALESCE() to preserve rows
  • count(NULL) returns 0—useful: OPTIONAL MATCH (u)-[:REVIEWED]->(p) RETURN count(p)
  • Property access on NULL throws no error, returns NULL—silent data loss

Direction

  • Query direction ignored with no arrow: (a)-[:KNOWS]-(b) matches both ways
  • Creation requires direction—must pick one, can't create undirected
  • Wrong direction = empty results—if relationship is (a)-[:OWNS]->(b), query (b)-[:OWNS]->(a) finds nothing

Batch Operations

  • Large creates in single transaction exhaust heap—use CALL {} IN TRANSACTIONS OF 1000 ROWS
  • UNWIND $list AS item CREATE (n:Node {id: item.id}) for batch inserts
  • apoc.periodic.iterate() for complex batch logic with progress
  • Delete in batches: MATCH (n:Old) WITH n LIMIT 10000 DETACH DELETE n in loop

Parameter Injection

  • Always use parameters $param not string concatenation—prevents Cypher injection
  • Parameters also enable query plan caching—literal values recompile each time
  • Pass as map: {param: value} in driver, :param {param: value} in browser
  • List parameter for IN: WHERE n.id IN $ids