TL;DR

  • 場景:圖數據庫項目中高頻用到的字符串函數、聚合、關係函數與 shortestPath,多跳查詢易踩坑。
  • 結論:以 Cypher 5/Neo4j 5.x 為基線,先掌握 toLower/trim/replace/split/substring/size、startNode/endNode、可變長度路徑;避免一次多語句與未綁定變量。
  • 產出:函數清單與示例整理、版本兼容矩陣、錯誤速查卡(覆蓋 WITH 傳參、shortestPath 約束、屬性缺失、類型不匹配等)。

CQL函數

字符串函數

neo4j查詢多跳關係的方法_neo4j 多跳查詢_#java

基本字符串函數

  1. toString()
  • 功能:將任意類型的值轉換為字符串形式
  • 示例:RETURN toString(123) → 返回 “123”
  • 應用場景:將數值、布爾值等非字符串類型轉換為字符串以便與其他字符串連接或比較
  1. toUpper()
  • 功能:將字符串轉換為大寫形式
  • 示例:RETURN toUpper("neo4j") → 返回 “NEO4J”
  • 應用場景:統一大小寫格式進行字符串比較或顯示
  1. toLower()
  • 功能:將字符串轉換為小寫形式
  • 示例:RETURN toLower("Neo4J") → 返回 “neo4j”
  • 應用場景:同上,用於標準化字符串格式

字符串操作函數

  1. trim()
  • 功能:去除字符串兩端的空白字符
  • 示例:RETURN trim(" Neo4j ") → 返回 “Neo4j”
  • 變體:
  • lTrim() - 僅去除左側空白
  • rTrim() - 僅去除右側空白
  1. replace()
  • 功能:替換字符串中的子串
  • 語法:replace(原始字符串, 要替換的子串, 替換為的子串)
  • 示例:RETURN replace("Hello World", "World", "Neo4j") → 返回 “Hello Neo4j”
  • 應用場景:批量修改數據中的特定文本
  1. substring()
  • 功能:提取字符串的一部分
  • 語法:
  • substring(字符串, 起始位置) (從0開始計數)
  • substring(字符串, 起始位置, 長度)
  • 示例:
  • RETURN substring("Neo4j", 3) → 返回 “4j”
  • RETURN substring("Neo4j", 1, 3) → 返回 “eo4”

字符串信息函數

  1. size()
  • 功能:返回字符串的字符長度
  • 示例:RETURN size("Neo4j") → 返回 5
  • 注意:與length()函數功能相同,可以互換使用
  1. split()
  • 功能:按分隔符將字符串分割為字符串數組
  • 示例:RETURN split("one,two,three", ",") → 返回 [“one”, “two”, “three”]
  • 應用場景:處理CSV格式的數據或路徑字符串
  1. reverse()
  • 功能:反轉字符串字符順序
  • 示例:RETURN reverse("Neo4j") → 返回 “j4oeN”

字符串匹配函數

  1. contains()
  • 功能:檢查字符串是否包含子串
  • 示例:RETURN contains("Neo4j", "4j") → 返回 true
  • 應用場景:數據篩選或條件判斷
  1. startsWith()
  • 功能:檢查字符串是否以指定前綴開頭
  • 示例:RETURN startsWith("Neo4j", "Neo") → 返回 true
  1. endsWith()
  • 功能:檢查字符串是否以指定後綴結尾
  • 示例:RETURN endsWith("Neo4j", "4j") → 返回 true
  1. left() / right()
  • 功能:
  • left(字符串, 長度) - 返回字符串左側指定長度的子串
  • right(字符串, 長度) - 返回字符串右側指定長度的子串
  • 示例:
  • RETURN left("Neo4j", 3) → 返回 “Neo”
  • RETURN right("Neo4j", 2) → 返回 “4j”

特殊字符串處理

  1. toStringOrNull()
  • 功能:嘗試將輸入轉換為字符串,失敗則返回null
  • toString()的區別:不會拋出異常,處理更安全
  1. toStringList()
  • 功能:將列表中的元素轉換為字符串列表
  • 示例:RETURN toStringList([1, 2, true]) → 返回 [“1”, “2”, “true”]

實際應用示例

// 查詢名稱以特定前綴開頭且經過標準化的用户
MATCH (u:User)
WHERE startsWith(toLower(u.name), 'alex')
RETURN u.name, size(u.name) as nameLength
// 處理地址數據,標準化格式
MATCH (a:Address)
SET a.city = toUpper(trim(a.city)),
    a.street = replace(a.street, "St.", "Street")

語法實例

基本的語法如下所示:

MATCH (p:Person)
RETURN ID(p),LOWER(p.character)

嘗試一個例子:

match(person:Person) RETURN ID(person), UPPER(person.character);

執行的結果如下所示,可以看到 UPPER 函數已經將結果轉換為大寫了:

neo4j查詢多跳關係的方法_neo4j 多跳查詢_#python_02

聚合函數

neo4j查詢多跳關係的方法_neo4j 多跳查詢_#數據庫_03

對應的語法格式如下所示:

MATCH (p:Person)
RETURN MAX(p.money),SUM(p.money)

執行結果可以看到已經計算出來了,後半段截圖沒有截到:

neo4j查詢多跳關係的方法_neo4j 多跳查詢_#數據庫_04

關係函數

neo4j查詢多跳關係的方法_neo4j 多跳查詢_#nosql_05

這裏我們元數據長這個樣子:

neo4j查詢多跳關係的方法_neo4j 多跳查詢_#nosql_06


然後我們查詢 wzk5 的 friend 關係的:

match p = (:Person{name: "wzk5"})-[r:Friend]-(:Person) return STARTNODE(r);

可以看到查詢到了 wzk4 的內容:

neo4j查詢多跳關係的方法_neo4j 多跳查詢_#數據庫_07

最短Path

MATCH p=shortestPath( (node1)-[*]-(node2) )
RETURN length(p), nodes(p)

CQL多深度關係點

with關鍵字

這裏我們加入一些內容,讓整體變得複雜起來:

// 清理舊數據 (可選)
// MATCH (n:Person) WHERE n.name STARTS WITH "wzk" DETACH DELETE n;


// ====== 創建節點 =======
UNWIND range(1, 10) AS i
MERGE (:Person {name:"wzk" + i});


// ====== 創建多樣關係 =======

// 1)鏈式關係(長鏈)
MATCH (a:Person {name:"wzk1"}), (b:Person {name:"wzk2"})
MERGE (a)-[:Follow]->(b);

MATCH (b:Person {name:"wzk2"}), (c:Person {name:"wzk3"})
MERGE (b)-[:Friends]->(c);

MATCH (c:Person {name:"wzk3"}), (d:Person {name:"wzk4"})
MERGE (c)-[:Colleague]->(d);

MATCH (d:Person {name:"wzk4"}), (e:Person {name:"wzk5"})
MERGE (d)-[:Knows]->(e);


// 2)三角結構(循環)
MATCH (p1:Person {name:"wzk3"}),(p2:Person {name:"wzk6"}),(p3:Person {name:"wzk7"})
MERGE (p1)-[:Friends]->(p2)
MERGE (p2)-[:Friends]->(p3)
MERGE (p3)-[:Friends]->(p1);


// 3)星型關係(hub-and-spoke)
MATCH (c:Person {name:"wzk5"}), (n:Person)
WHERE n.name IN ["wzk6","wzk7","wzk8","wzk9"]
MERGE (c)-[:Follow]->(n)
MERGE (n)-[:Knows]->(c);


// 4)雙向 Couple(特意製造有向+無向混合)
MATCH (a:Person {name:"wzk1"}),(b:Person {name:"wzk8"})
MERGE (a)-[:Couple]->(b)
MERGE (b)-[:Couple]->(a);


// 5)複雜跨層跳躍
MATCH (x:Person {name:"wzk9"}),(y:Person {name:"wzk10"})
MERGE (x)-[:Colleague]->(y);

MATCH (y:Person {name:"wzk10"}),(z:Person {name:"wzk2"})
MERGE (y)-[:Follow]->(z);


// 6)製造稠密關係(高節點度,用於性能測試)
MATCH (p:Person), (p2:Person)
WHERE p.name STARTS WITH "wzk"
  AND p2.name STARTS WITH "wzk"
  AND p <> p2
  AND rand() < 0.15   // 15% 概率生成一條邊
MERGE (p)-[:Knows]->(p2);

整體執行完之後,會生成類似這樣的結構:

neo4j查詢多跳關係的方法_neo4j 多跳查詢_#java_08

直接拼接關係節點查詢

match (na:Person{name:"wzk1"})-[re]->(nb:Person)-[re2]->(nc:Person) return na,re,nb,re2,nc

運行結果如下所示:

neo4j查詢多跳關係的方法_neo4j 多跳查詢_#java_09

使用深度運算符

當實現多深度關係節點查詢時,顯然使用以上方式比較繁瑣。

match data = (na:Person{name:"wzk1"})-[*1..2]-(nb:Person) return data

執行結果如下所示:

neo4j查詢多跳關係的方法_neo4j 多跳查詢_#數據庫_10