name: neo4j-cypher-query-analyze version: 1.0.0 description: 智慧圖資料庫查詢助手 - 自動感知 Schema 結構,根據自然語言生成精準的 Cypher 查詢 trigger: "圖查詢|graph query|cypher|知識圖譜|neo4j查詢|圖譜分析" tools: [shell, http, filesystem, memory] author: your-name metadata: openclaw: emoji: 🧠 requires: bins: ["curl"] env: ["GRAPHDB_URI", "GRAPHDB_USER", "GRAPHDB_PASSWORD", "GRAPHDB_DATABASE"] optional_env: ["GRAPHDB_TYPE"] # neo4j, neptune, janusgraph
使用者提問 → Schema 獲取(如需要) → 意圖分析 → Cypher 生成 → 安全檢查 → 執行查詢 → 結果格式化
在首次查詢或 Schema 快取過期時,執行以下探測查詢:
1. 獲取所有節點標籤
CALL db.labels() YIELD label RETURN collect(label) AS nodeLabels
2. 獲取所有關係型別
CALL db.relationshipTypes() YIELD relationshipType RETURN collect(relationshipType) AS relTypes
3. 獲取屬性鍵(可選,用於理解常用屬性)
CALL db.propertyKeys() YIELD propertyKey RETURN collect(propertyKey) AS propertyKeys
4. 獲取 Schema 視覺化(Neo4j 特定)
CALL db.schema.visualization()
5. 取樣各標籤的典型節點(理解屬性結構) 對每個重要標籤執行:
MATCH (n:LabelName)
RETURN n LIMIT 1
6. 取樣關係結構
MATCH ()-[r:REL_TYPE]->()
RETURN type(r) as rel_type, keys(r) as properties LIMIT 1
使用 memory 工具快取 Schema 資訊:
# 快取鍵: graphdb_schema_{database_name}
# 內容結構:
schema_cache:
timestamp: "2024-01-15T10:30:00Z"
ttl_hours: 24
node_labels:
- Person:
sample_properties: [name, age, email, created_at]
estimated_count: 15000
- Company:
sample_properties: [name, industry, registered_capital]
estimated_count: 5000
- Product:
sample_properties: [name, category, price]
relationship_types:
- WORKS_AT:
start_labels: [Person]
end_labels: [Company]
properties: [since, position]
- MANAGES:
start_labels: [Person]
end_labels: [Person]
- PRODUCES:
start_labels: [Company]
end_labels: [Product]
indexes:
- :Person(id)
- :Company(name)
constraints:
- :Person(email) UNIQUE
將使用者查詢分類為以下模式:
| 查詢模式 | 描述 | 示例 |
|---|---|---|
| 實體查詢 | 按屬性查詢特定節點 | "查詢叫張三的客戶" |
| 關係探索 | 查詢節點的關聯關係 | "張三的朋友有哪些" |
| 路徑發現 | 查詢兩個節點間的路徑 | "張三和李四之間有什麼關係" |
| 模式匹配 | 特定子圖結構查詢 | "查詢三角擔保關係" |
| 統計分析 | 聚合計算 | "每個公司的平均員工數" |
| 後設資料查詢 | 查詢 Schema 本身 | "資料庫裡有哪些實體型別" |
基於 Schema 快取生成查詢時遵循:
1. 標籤匹配規則
- 使用者提到的實體名稱 → 匹配 node_labels 中最相似的標籤
- 使用 Levenshtein 距離或語義相似度進行模糊匹配
- 歧義時詢問使用者確認(如 "客戶" 對應 Customer 還是 Client)
2. 屬性推斷規則
- 優先使用索引屬性(如 id, email)進行過濾
- 字串匹配使用 CONTAINS 或 STARTS WITH 而非精確匹配(除非使用者明確)
- 數值範圍使用 >= 和 <=
3. 關係導航規則
- 根據 Schema 確定有效的 (start_label)-[REL]->(end_label) 組合
- 雙向關係使用 -[:REL]- 而非 ->
- 多跳查詢限制最大深度(預設 3,防止路徑爆炸)
4. 效能最佳化規則
- 所有查詢必須包含 LIMIT(預設 100,最大 1000)
- 避免 MATCH (n) 全節點掃描
- 優先使用 MATCH 而非 OPTIONAL MATCH 除非明確需要
- 複雜聚合使用 WITH 進行管道處理
在執行前進行多層審查:
1. 操作型別檢查
# 虛擬碼邏輯
write_keywords = ['CREATE', 'DELETE', 'SET', 'REMOVE', 'MERGE', 'DROP', 'LOAD']
if any(kw in query.upper() for kw in write_keywords):
require_explicit_confirmation()
log_audit_trail()
2. 複雜度評估 - 計算估計的節點掃描量(基於標籤選擇性和過濾條件) - 深度超過 4 的關係路徑查詢需要警告 - 全圖遍歷查詢(無標籤限制)直接拒絕
3. 敏感資料保護
- 檢測到屬性名包含 password, token, secret, ssn 時自動脫敏
- 返回前掃描結果集,對敏感欄位進行掩碼處理(如 ***)
4. 超時控制 - 設定 30 秒查詢超時 - 超時後自動終止並建議最佳化查詢(新增索引提示或限制條件)
HTTP API 呼叫模板:
# Neo4j HTTP API
curl -s -X POST \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-u "${GRAPHDB_USER}:${GRAPHDB_PASSWORD}" \
"${GRAPHDB_URI}/db/${GRAPHDB_DATABASE}/tx/commit" \
-d "{
\"statements\": [{
\"statement\": \"${CYPHER_QUERY}\",
\"parameters\": ${PARAMETERS_JSON:-{}},
\"resultDataContents\": [\"row\", \"graph\"]
}]
}" 2>&1
錯誤分類處理:
| 錯誤型別 | 識別特徵 | 處理策略 |
|---|---|---|
| 連線失敗 | Failed to connect, Connection refused |
檢查 URI 和網路,提示驗證服務狀態 |
| 認證失敗 | Unauthorized, Authentication failed |
提示檢查使用者名稱密碼,不暴露具體錯誤 |
| 語法錯誤 | InvalidSyntax, SyntaxError |
展示生成的查詢,高亮錯誤位置,建議修正 |
| 語義錯誤 | Label not found, Property not found |
對比 Schema 快取,提示可用的標籤/屬性 |
| 效能超時 | Transaction timed out |
建議新增 LIMIT、縮小過濾範圍、或建立索引 |
| 許可權不足 | Forbidden, Access denied |
提示當前使用者許可權限制,建議聯絡管理員 |
根據返回資料型別自動選擇最佳展示方式:
1. 表格檢視(預設) 適用於:屬性列表、聚合統計
| 姓名 | 年齡 | 所屬公司 | 入職年份 |
|------|------|----------|----------|
| 張三 | 32 | 科技有限公司 | 2019 |
| 李四 | 28 | 創新網路公司 | 2021 |
2. 關係圖譜描述 適用於:路徑、子圖結構
**關係路徑 (長度: 2)**
張三 (Person, 35歲) -[WORKS_AT {since: 2019, position: "工程師"}]->
科技有限公司 (Company, 網際網路) -[PRODUCES {category: "SaaS"}]->
智慧雲平臺 (Product, 2023年釋出)
3. 統計卡片 適用於:聚合查詢
📊 **統計結果**
- 總節點數: 1,234
- 平均年齡: 34.5 歲
- 最大關係深度: 5
- 最密集連線節點: 科技有限公司 (連線數: 156)
4. JSON 原始資料 適用於:開發者除錯、後續程式處理
{
"columns": ["name", "count"],
"data": [
{"name": "科技有限公司", "count": 42},
{"name": "創新網路", "count": 28}
]
}
使用者輸入: "查詢所有在科技有限公司工作的工程師,並顯示他們的入職年份"
執行流程:
memory 工具:無有效快取或快取過期決定:執行 Schema 探測
Schema 探測執行 ```bash # 獲取標籤 curl ... -d '{"statements":[{"statement":"CALL db.labels() YIELD label RETURN collect(label) AS labels"}]}' # 返回: ["Person", "Company", "Product", "Department"]
# 獲取關係型別 curl ... -d '{"statements":[{"statement":"CALL db.relationshipTypes() YIELD relationshipType RETURN collect(relationshipType) AS types"}]}' # 返回: ["WORKS_AT", "MANAGES", "BELONGS_TO", "PRODUCES"]
# 取樣 Person 節點 curl ... -d '{"statements":[{"statement":"MATCH (p:Person) RETURN p LIMIT 2"}]}' # 返回屬性: name, age, position, email, hire_date
# 取樣 WORKS_AT 關係 curl ... -d '{"statements":[{"statement":"MATCH ()-[r:WORKS_AT]->() RETURN r LIMIT 1"}]}' # 返回屬性: since, department, level ```
Company.name(模糊匹配)Person.position 或 WORKS_AT.levelPerson -[WORKS_AT]-> Company 是有效路徑屬性確認:hire_date 或 WORKS_AT.since 可用於"入職年份"
生成 Cypher
cypher
MATCH (p:Person)-[w:WORKS_AT]->(c:Company)
WHERE c.name CONTAINS '科技' AND
(p.position CONTAINS '工程師' OR w.level CONTAINS '工程師')
RETURN p.name AS 姓名,
p.age AS 年齡,
c.name AS 公司,
w.since AS 入職年份,
w.department AS 部門
ORDER BY w.since DESC
LIMIT 50
安全檢查
✓ 無敏感欄位暴露風險
執行查詢 → 獲取結果
格式化輸出 ```markdown 🔍 查詢結果: 找到 12 位工程師
| 姓名 | 年齡 | 公司 | 入職年份 | 部門 |
|---|---|---|---|---|
| 王五 | 29 | 科技有限公司 | 2021 | 研發部 |
| 趙六 | 34 | 科技有限公司 | 2019 | 產品部 |
| ... | ... | ... | ... | ... |
📈 統計: 平均工齡 3.5 年,最早入職者為 2015 年 ```
memory:graphdb_schema_defaultPerson-WORKS_AT-Company 關聯查詢使用者輸入: "顯示這些工程師的管理者是誰"
執行流程:
memory 獲取:graphdb_schema_default確認快取有效(< 24 小時)
上下文關聯
Person 結果集或者理解為:查詢所有工程師的管理者
Schema 輔助生成
MANAGES 關係:Person -[MANAGES]-> Personp<-[:MANAGES]-(manager) 或 p-[:MANAGES]->(subordinate)根據"管理者"語義,確定為入邊方向
生成 Cypher
cypher
MATCH (p:Person)-[:WORKS_AT]->(c:Company)
WHERE c.name CONTAINS '科技' AND p.position CONTAINS '工程師'
OPTIONAL MATCH (manager:Person)-[:MANAGES]->(p)
RETURN p.name AS 工程師,
manager.name AS 直接上級,
manager.position AS 上級職位
LIMIT 50
執行與返回
當用戶問"為什麼會這樣查"時,展示推理過程:
**🧠 查詢推理過程**
1. **實體識別**:
- "工程師" → 匹配到標籤 `Person`,屬性 `position`(置信度 0.92)
- "科技有限公司" → 匹配到標籤 `Company`,屬性 `name`(模糊匹配)
2. **關係推斷**:
- 人員與公司的工作關係 → Schema 中存在 `WORKS_AT` 關係
- 方向確定為 `(Person)-[:WORKS_AT]->(Company)`
3. **過濾條件**:
- 使用 `CONTAINS` 而非 `=`,因為使用者可能輸入公司簡稱
- 工程師匹配同時檢查 `Person.position` 和 `WORKS_AT.level`(增加召回率)
4. **效能最佳化**:
- 假設 `Company.name` 有索引(從 Schema 後設資料確認)
- 新增 `LIMIT 50` 防止大數據集效能問題
對於複雜查詢,支援分步構建:
使用者: "查詢風險等級為高的客戶"
→ 執行,返回結果
使用者: "只看那些擔保金額超過 100 萬的"
→ 理解上下文,在上次查詢基礎上新增:
MATCH (c:Customer {risk_level: 'HIGH'})-[g:GUARANTEE]-(target)
WHERE g.amount > 1000000
RETURN ...
每次查詢前快速驗證 Schema 版本:
CALL dbms.components() YIELD versions
如果檢測到版本變更或快取過期,自動重新整理 Schema。
~/.openclaw/skills/graphdb-schema-aware-query/.env
~/.openclaw/skills/graphdb-schema-aware-query/config.yaml
使用者: "查詢姓張的所有客戶,按註冊時間排序"
AI 思考:
- Schema 確認:存在 Customer 標籤,有 name 和 registered_at 屬性
- 生成:MATCH (c:Customer) WHERE c.name STARTS WITH '張' RETURN c ORDER BY c.registered_at DESC LIMIT 50
使用者: "顯示客戶 C10086 的所有擔保關係,包括被擔保方和擔保金額"
AI 思考:
- Schema 確認:存在 GUARANTEE 關係,有 amount 屬性
- 方向確認:Customer -[GUARANTEE]-> Customer(自查 Schema 快取)
- 生成:雙向查詢確保捕獲擔保和被擔保
MATCH (c:Customer {id: 'C10086'})-[g:GUARANTEE]-(other:Customer)
RETURN other.name AS 相關客戶,
type(g) AS 關係型別,
g.amount AS 擔保金額,
CASE WHEN startNode(g) = c THEN '對外擔保' ELSE '被擔保' END AS 方向
ORDER BY g.amount DESC
使用者: "張三和李四之間是否存在任何間接的投資關係?"
AI 思考:
- Schema 確認:存在 INVEST 關係,連線 Person 或 Company
- 路徑分析:需要可變長度路徑,最大深度 3
- 生成:
MATCH path = (a:Person {name: '張三'})-[*1..3]-(b:Person {name: '李四'})
WHERE ALL(r IN relationships(path) WHERE type(r) = 'INVEST')
RETURN path, length(path) AS 層級
LIMIT 10
使用者: "這個資料庫裡儲存了哪些型別的資料?"
AI 思考: - 識別為後設資料查詢,直接返回 Schema 快取內容 - 無需執行 Cypher,從快取提取標籤和關係統計
db.schema.visualization()(3.5+)SHOW USER PRIVILEGESCALL db.labels() + CALL db.relationshipTypes() 組合本技能來自小蔥技能站7w4.net。
強制重新整理 schemaEXPLAIN 模式先檢視生成的查詢不執行*1..5 改為 *1..3)PROFILE 分析查詢計劃,建議建立缺失索引這個Skill設計思路不錯,能幫你用自然語言查詢圖資料庫。但整體更像一份設計藍圖,實際可用的內容偏少。沒有使用示例,配置說明也不夠直觀,如果你想直接上手使用可能需要自己補充不少內容。文件本身質量尚可,但配套實現不夠完整。