Cypher查詢語言--Neo4j中的SQL(1)
“Cypher”是一個描述性的圖形查詢語言,允許不必編寫圖形結構的遍歷程式碼對圖形儲存有表現力和效率的查詢。Cypher還在繼續發展和成熟,這也就意味著有可能會出現語法的變化。同時也意味著作為元件沒有經歷嚴格的效能測試。
Cypher設計的目的是一個人類查詢語言,適合於開發者和在資料庫上做點對點模式(ad-hoc)查詢的專業操作人員(我認為這個很重要)。它的構念是基於英語單詞和靈巧的圖解。
Cyper通過一系列不同的方法和建立於確定的實踐為表達查詢而激發的。許多關鍵字如like和order by是受SQL的啟發。模式匹配的表示式來自於SPARQL。正則表示式匹配實現實用
Cypher是一個申明式的語言。對比命令式語言如Java和指令碼語言如Gremlin和JRuby,它的焦點在於從圖中如何找回(what to retrieve),而不是怎麼去做。這使得在不對使用者公佈的實現細節裡關心的是怎麼優化查詢。
這個查詢語言包含以下幾個明顯的部分:
Ø START:在圖中的開始點,通過元素的ID或所以查詢獲得。
Ø MATCH:圖形的匹配模式,束縛於開始點。
Ø WHERE:過濾條件。
Ø RETURN:返回所需要的。
在下例中看三個關鍵字
示例圖片如下:
如:這個有個查詢,通過遍歷圖找到索引裡一個叫John的朋友的朋友(不是他的直接朋友),返回John和找到的朋友的朋友。
START john=node:node_auto_index(name = 'John')
MATCH john-[:friend]->()-[:friend]->fof
RETURN john, fof
返回結果:
下一步新增過濾:
在下一個例子中,列出一組使用者的id並遍歷圖查詢這些使用者接出friend關係線,返回有屬性name並且其值是以S開始的使用者。
START user=node(5,4,1,2,3)
MATCH user-[:friend]->follower
WHERE follower.name =~ /S.*/
RETURN user, follower.name
返回結果:
操作符
Cypher中的操作符有三個不同種類:數學,相等和關係。
數學操作符有+,-,*,/和%。當然只有+對字元有作用。
等於操作符有=,<>,<,>,<=,>=。
因為Neo4j是一個模式少的圖形資料庫,Cypher有兩個特殊的操作符?和!。
有些是用在屬性上,有些事用於處理缺少值。對於一個不存在的屬性做比較會導致錯誤。為替代與其他什麼做比較時總是檢查屬性是否存在,在缺失屬性時問號將使得比較總是返回true,感嘆號使得比較總是返回false。
WHEREn.prop? = "foo"
WHEREn.prop! = "foo"
這個斷言在屬性缺失情況下將評估為false。
警告:在同一個比較中混合使用兩個符號將導致不可預料的結果。
引數
Cypher支援帶引數的查詢。這允許開發者不需要必須構建一個string的查詢,並且使得Cypher的查詢計劃的快取更容易。
引數可以在where子句,start子句的索引key或索引值,索引查詢中作為節點/關係id的引用。
以下是幾個在java中使用引數的示例:
節點id引數
Map<String, Object> params = new HashMap<String, Object>(); params.put( "id", 0 ); ExecutionResult result = engine.execute( "start n=node({id}) return n.name", params ); |
節點物件引數
Map<String, Object> params = new HashMap<String, Object>(); params.put( "node", andreasNode ); ExecutionResult result = engine.execute( "start n=node({node}) return n.name", params ); |
多節點id引數
Map<String, Object> params = new HashMap<String, Object>(); params.put( "id", Arrays.asList( 0, 1, 2 ) ); ExecutionResult result = engine.execute( "start n=node({id}) return n.name", params ); |
字串引數
Map<String, Object> params = new HashMap<String, Object>(); params.put( "name", "Johan" ); ExecutionResult result = engine.execute( "start n=node(0,1,2) where n.name = {name} return n", params ); |
索引鍵值引數
Map<String, Object> params = new HashMap<String, Object>(); params.put( "key", "name" ); params.put( "value", "Michaela" ); ExecutionResult result = engine.execute( "start n=node:people({key} = {value}) return n", params ); |
索引查詢引數
Map<String, Object> params = new HashMap<String, Object>(); params.put( "query", "name:Andreas" ); ExecutionResult result = engine.execute( "start n=node:people({query}) return n", params ); |
- SKIP 與LIMIT * 的數字引數
Map<String, Object> params = new HashMap<String, Object>(); params.put( "s", 1 ); params.put( "l", 1 ); ExecutionResult result = engine.execute( "start n=node(0,1,2) return n.name skip {s} limit {l}", params ); |
- 正則表示式引數
Map<String, Object> params = new HashMap<String, Object>(); params.put( "regex", ".*h.*" ); ExecutionResult result = engine.execute( "start n=node(0,1,2) where n.name =~ {regex} return n.name", params ); |
識別符號
當你參考部分的模式時,需要通過命名完成。定義的不同的命名部分就被稱為識別符號。
如下例中:
START n=node(1) MATCH n-->b RETURN b
識別符號為n和b。
識別符號可以是大寫或小些,可以包含下劃線。當需要其他字元時可以使用`符號。對於屬性名的規則也是一樣。
註解
可以在查詢語句中使用雙斜槓來添加註解。如:
START n=node(1) RETURN b //這是行結束註釋
START n=node(1) RETURN b
START n=node(1) WHERE n.property = "//這部是一個註釋" RETURN b
Start
每一個查詢都是描述一個圖案(模式),在這個圖案(模式)中可以有多個限制點。一個限制點是為模式匹配的從開始點出發的一條關係或一個節點。可以通過id或索引查詢繫結點。
通過id繫結點
通過node(*)函式繫結一個節點作為開始點
查詢:
START n=node(1)
RETURN n
返回引用的節點。
結果:
通過id繫結關係
可以通過relationship()函式繫結一個關係作為開始點。也可以通過縮寫rel()。
查詢:
START r=relationship(0)
RETURN r
Id為0的關係將被返回
結果:
通過id繫結多個節點
選擇多個節點可以通過逗號分開。
查詢:
START n=node(1, 2, 3)
RETURN n
結果:
所有節點
得到所有節點可以通過星號(*),同樣對於關係也適用。
查詢:
START n=node(*)
RETURN n
這個查詢將返回圖中所有節點。
結果:
通過索引查詢獲取節點
如果開始節點可以通過索引查詢得到,可以如此來寫:
node:index-name(key=”value”)。在此列子中存在一個節點索引叫nodes。
查詢:
START n=node:nodes(name = "A")
RETURN n
索引中命名為A的節點將被返回。
結果:
通過索引查詢獲取關係
如果開始點可以通過索引查詢得到,可以如此做:
Relationship:index-name(key=”value”)。
查詢:
START r=relationship:rels(property ="some_value")
RETURN r
索引中屬性名為”some_value”的關係將被返回。
結果:
多個開始點
有時需要繫結多個開始點。只需要列出並以逗號分隔開。
查詢:
START a=node(1), b=node(2)
RETURN a,b
A和B兩個節點都將被返回。
結果: