1. Cypher介紹
“Cypher”是一個描述性的圖形查詢語言,允許不必編寫圖形結構的遍歷代碼對圖形存儲有表現力和效率的查詢。Cypher還在繼續發展和成熟,這也就意味著有可能會出現語法的變化。同時也意味著作為組件沒有經歷嚴格的性能測試。
Cypher設計的目的是一個人類查詢語言,適合于開發者和在數據庫上做點對點模式(ad-hoc)查詢的專業操作人員。它的構念是基于英語單詞和靈巧的圖解。
Cyper通過一系列不同的方法和建立于確定的實踐為表達查詢而激發的。許多關鍵字如like和order by是受SQL的啟發。模式匹配的表達式來自于SPARQL。正則表達式匹配實現實用Scala programming language語言。
Cypher是一個申明式的語言。對比命令式語言如Java和腳本語言如Gremlin和JRuby,它的焦點在于從圖中如何找回(what to retrieve),而不是怎么去做。這使得在不對用戶公布的實現細節里關心的是怎么優化查詢。
Neo4j使用Cypher查詢圖形數據,和SQL很相似,Cypher語言的關鍵字不區分大小寫,但是屬性值,標簽,關系類型和變量是區分大小寫的。
2. 基本語法
Cypher使用一對圓括號來表示一個節點:
提供了多種格式如下:
() 匿名節點
(matrix) 為節點添加一個ID
(:Movie) Movie label標簽,聲明的是節點類型。noe4j的索引使用label,每個索引由標簽和屬性組成
(matrix:Movie)
(matrix:Movie {title: "The Matrix"}) 節點屬性(如:title)代表一個key\value 的List
(matrix:Movie {title: "The Matrix", released: 1997})
RelationShip語法:
-- 表示一個無指向的關系
--> 表示一個有指向的關系
[] 能夠添加ID,屬性,類型等信息
-[role]->
-[:ACTED_IN]->
-[role:ACTED_IN]->
-[role:ACTED_IN {roles: ["Neo"]}]->
Pattern 語法:
節點和關系語法的合并就表示模式。
(keanu:Person:Actor {name: "Keanu Reeves"} )
-[role:ACTED_IN {roles: ["Neo"] } ]->
(matrix:Movie {title: "The Matrix"} )
Pattern Identifiers :
為模式分配ID,為例增加模塊化和重復使用
acted_in = (:Person)-[:ACTED_IN]->(:Movie)
3. 創建節點
節點模式的構成:(Variable:Lable1:Lable2{Key1:Value1,Key2,Value2}),實際上,每個節點都有一個整數ID,在創建新的節點時,Neo4j自動為節點設置ID值,在整個數據庫中,節點的ID值是遞增的和唯一的。
下面的Cypher查詢創建一個節點,標簽是Person,具有兩個屬性name和born,通過RETURN子句,返回新建的節點:
create (n:Person { name: 'Tom Hanks', born: 1956 }) return n;
繼續創建其他節點:
create (n:Person { name: 'Robert Zemeckis', born: 1951 }) return n;
create (n:Movie { title: 'Forrest Gump', released: 1951 }) return n;
4. 查詢節點
通過match子句查詢數據庫,match子句用于指定搜索的模式(Pattern),where子句為match模式增加謂詞(Predicate),用于對Pattern進行約束;
4.1 查詢整個圖形數據庫
match(n) return n;
在圖形數據庫中,有三個節點,Person標簽有連個節點,Movie有1個節點
4.2 查詢born屬性小于1952的節點
match(n)
where n.born<1952
return n;
4.3 查詢具有指定Lable的節點
match(n:Movie)
return n;
4. 創建關系
關系的構成:StartNode - [Variable:RelationshipType{Key1:Value1,Key2:Value2}] -> EndNode,在創建關系時,必須指定關系類型。
4.1 創建沒有任何屬性的關系
MATCH (a:Person),(b:Movie)
WHERE a.name = 'Robert Zemeckis' AND b.title = 'Forrest Gump'
CREATE (a)-[r:DIRECTED]->(b)
RETURN r;
4.2 創建關系,并設置關系的屬性
MATCH (a:Person),(b:Movie)
WHERE a.name = 'Tom Hanks' AND b.title = 'Forrest Gump'
CREATE (a)-[r:ACTED_IN { roles:['Forrest'] }]->(b)
RETURN r;
5. 查詢關系
在Cypher中,關系分為三種:符號--
,表示有關系,忽略關系的類型和方向;符號-->
和<--
,表示有方向的關系;
5.1 查詢整個數據圖形
match(n) return n;
5.2 查詢跟指定節點有關系的節點
示例腳本返回跟Movie標簽有關系的所有節點
match(n)--(m:Movie)
return n;
5.2 查詢有向關系的節點
MATCH (:Person { name: 'Tom Hanks' })-->(movie)
RETURN movie;
5.3 為關系命名,通過[r]為關系定義一個變量名,通過函數type獲取關系的類型
MATCH (:Person { name: 'Tom Hanks' })-[r]->(movie)
RETURN r,type(r);
5.4 查詢特定的關系類型,通過[Variable:RelationshipType{Key:Value}]指定關系的類型和屬性
MATCH (:Person { name: 'Tom Hanks' })-[r:ACTED_IN{roles:'Forrest'}]->(movie)
RETURN r,type(r);
6. 更新操作
set子句,用于對更新節點的標簽和實體的屬性;remove子句用于移除實體的屬性和節點的標簽;
6.1 創建一個完整的Path
由于Path是由節點和關系構成的,當路徑中的關系或節點不存在時,Neo4j會自動創建;
CREATE p =(vic:Worker:Person{ name:'vic',title:"Developer" })-[:WORKS_AT]->(neo)<-[:WORKS_AT]-(michael:Worker:Person { name: 'Michael',title:"Manager" })
RETURN p
變量neo代表的節點沒有任何屬性,但是,其有一個ID值,通過ID值為該節點設置屬性和標簽
6.2 為節點增加屬性
通過節點的ID獲取節點,Neo4j推薦通過where子句和ID函數來實現。
match (n)
where id(n)=7
set n.name = 'neo'
return n;
6.3 為節點增加標簽
match (n)
where id(n)=7
set n:Company
return n;
6.4 為關系增加屬性
match (n)<-[r]-(m)
where id(n)=7 and id(m)=8
set r.team='Azure'
return n;
7. Merge子句
Merge子句的作用有兩個:當模式(Pattern)存在時,匹配該模式;當模式不存在時,創建新的模式,功能是match子句和create的組合。在merge子句之后,可以顯式指定on create和on match子句,用于修改綁定的節點或關系的屬性。
通過merge子句,你可以指定圖形中必須存在一個節點,該節點必須具有特定的標簽,屬性等,如果不存在,那么merge子句將創建相應的節點。
7.1 通過merge子句匹配搜索模式
匹配模式是:一個節點有Person標簽,并且具有name屬性;如果數據庫不存在該模式,那么創建新的節點;如果存在該模式,那么綁定該節點;
MERGE (michael:Person { name: 'Michael Douglas' })
RETURN michael;
7.2 在merge子句中指定on create子句
如果需要創建節點,那么執行on create子句,修改節點的屬性;
ERGE (keanu:Person { name: 'Keanu Reeves' })
ON CREATE SET keanu.created = timestamp()
RETURN keanu.name, keanu.created
7.3 在merge子句中指定on match子句
如果節點已經存在于數據庫中,那么執行on match子句,修改節點的屬性;
MERGE (person:Person)
ON MATCH SET person.found = TRUE , person.lastAccessed = timestamp()
RETURN person.name, person.found, person.lastAccessed
7.4 在merge子句中同時指定on create 和 on match子句
MERGE (keanu:Person { name: 'Keanu Reeves' })
ON CREATE SET keanu.created = timestamp()
ON MATCH SET keanu.lastSeen = timestamp()
RETURN keanu.name, keanu.created, keanu.lastSeen
7.5 merge子句用于match或create一個關系
MATCH (charlie:Person { name: 'Charlie Sheen' }),(wallStreet:Movie { title: 'Wall Street' })
MERGE (charlie)-[r:ACTED_IN]->(wallStreet)
RETURN charlie.name, type(r), wallStreet.title
7.6 merge子句用于match或create多個關系
MATCH (oliver:Person { name: 'Oliver Stone' }),(reiner:Person { name: 'Rob Reiner' })
MERGE (oliver)-[:DIRECTED]->(movie:Movie)<-[:ACTED_IN]-(reiner)
RETURN movie
7.7 merge子句用于子查詢
MATCH (person:Person)
MERGE (city:City { name: person.bornIn })
RETURN person.name, person.bornIn, city;
MATCH (person:Person)
MERGE (person)-[r:HAS_CHAUFFEUR]->(chauffeur:Chauffeur { name: person.chauffeurName })
RETURN person.name, person.chauffeurName, chauffeur;
MATCH (person:Person)
MERGE (city:City { name: person.bornIn })
MERGE (person)-[r:BORN_IN]->(city)
RETURN person.name, person.bornIn, city;
8. 跟實體相關的函數
8.1 通過id函數,返回節點或關系的ID
MATCH (:Person { name: 'Oliver Stone' })-[r]->(movie)
RETURN id(r);
8.2 通過type函數,查詢關系的類型
MATCH (:Person { name: 'Oliver Stone' })-[r]->(movie)
RETURN type(r);
8.3 通過lables函數,查詢節點的標簽
MATCH (:Person { name: 'Oliver Stone' })-[r]->(movie)
RETURN lables(movie);
8.4 通過keys函數,查看節點或關系的屬性鍵
MATCH (a)
WHERE a.name = 'Alice'
RETURN keys(a)
8.5 通過properties()函數,查看節點或關系的屬性
CREATE (p:Person { name: 'Stefan', city: 'Berlin' })
RETURN properties(p)