2013年12月19日 星期四

Neo4j: Cypher語法筆記:Match語法

MATCH syntax in Neo4j is for search.
Search the node, relationship...

*******

基本上Neo4j的語法組成跟SQL很像。
MATCH跟SELECT的功能有點像。
就是挑出符合條件的資料,最後可以配合WHERE過濾。
MATCH符合的內容,最後被RETURN。
就是一個簡單的Cypher語法。

Neo4j官方有提供「沙盒」(Sandbox),你可以任意操作。

先介紹節點的搜尋
如果你想要Neo4j列出所有的節點,語法如下:
MATCH (n)
RETURN (n)

MATCH跟RETURN都是保留字,可以用小寫也沒關係。

節點是可以有標籤的(label)
如果要找到所有標籤為NCBI的節點
MATCH (journal:NCBI)
RETURN journal

journal就是代表節點的變數,:NCBI如同認知,是個標籤
(複習一下,標籤就是冒號:起頭,冒號右邊是標籤名稱)

現在要找有關係的節點(Related nodes)
以官方網站的語法例子為例
MATCH (director {name:"Oliver Stone"})--(movie)
RETURN movie.title

就是先找出一個path,主要是導演跟電影的關係
然後要回傳的是電影節點中的標題屬性
你可以測試RETURN的變化,去了解Neo4j的語法規則。
例如RETURN movie,會RETURN所有的東西,不只是Title

像那個director,也只是一個暫時指派的變數而已。
目的是方便理解,movie也是。
在實際設計的些語法的時候,本來就要考量可讀性跟維護性。
重點在{name:"Oliver Stone"}的地方,這是MATCH的關鍵。
要找到所有跟Oliver Stone有關係的電影。
(這是已經假設案例跟電影有關,Neo4j的沙盒網站預設的)
不信你可以把director跟movie換掉試試看。

繼續是搜尋有向的關係,網站的例子是
MATCH (martin {name:"Martin Sheen"})-->(movie)
RETURN movie.title

要找的是屬性名為Martin Sheen向外發展的節點
如果你從官方的沙盒細看,會發現查詢結果的關係是:ACTED_IN
指的是Martin Sheen有演過的電影,以他為中心出發的有向查詢

至於這層有向的關係是什麼呢?請繼續看官方的範例
MATCH (martin {name:"Martin Sheen"})-[r]->(movie)
RETURN r

也就是把上面的範例小改,多加入一個表示關係的r變數
現在RETURN查詢結果r,顯示所有的關係

關係可以是未知,只要有關係就全部列出來,如上例。
也可以列出已知關係的節點,像是我要知道誰有演某部電影。
官方網站的範例語法如下
MATCH (wall street {title:"Wall Street"})<-[:ACTED_IN]-(actor)
RETURN actor

這兩行語法,重點的地方在{title:"Wall Street"}還有 <-[:ACTED_IN]-
請特別注意我把關係的箭頭方向有列出來
就語意上的意思是我要找誰有在Wall Street這部電影中演出。
執行之後就會列出演員了。

再多一個小變化,就可以有多重關係的查詢結果
MATCH (wall street {title:"Wall Street"})<-[:ACTED_IN|:DIRECTED]-(person)
RETURN person

現在要找的是Wall Street這部電影中,導戲跟演戲的人
原本那個actor也順勢換成person,目的是方便理解。
現在不只是找actor而已。

查詢多重關係也可以,例如想知道誰演某部電影、導演是誰。
然後現有條件只知道演員,可以用下列的範例語法:
MATCH (charlie {name:"Charlie Sheen"})-[:ACTED_IN]->(movie)<-[:DIRECTED]->(director)
RETURN charlie, movie, director

查詢結果會回傳三個「節點」,這是原本的範例內容。
一樣,可以自己變化。例如只回傳電影標題、導演名稱:
RETURN movie.title , director.name


想知道某演員演過的電影之間的可能關係,包含電影跟演員。
然後只要一到兩層的關係就好。
(我的理解是可能只想知道被查詢演員有跟誰又共演一齣戲。
這是根據下列查詢語法回應而推斷的)

MATCH (martin {name: "Martin Sheen"})-[:ACTED_IN*1..2]-(x)
RETURN x

執行之後只會列出被ACTED_IN關係最少一層,最多兩層的節點


*******

先寫到這樣,之後想到再補。
或者有需要可以參考官方網站資料,有非常華麗的功能。
例如尋找最短路徑。




2013年12月18日 星期三

Neo4j: Cypher語法筆記:呈現形式 Pattern

Pattern is an important part of Cypher syntax.
To represent the node, property and relationship.

*******

Pattern不知道該怎麼翻譯比較好。
說是模式、形式應該都可以,重點在內容的呈現。
對於Neo4j這個NoSQL型態的圖資料庫而言。
每一筆資料可以是一個節點Node
節點的表達就是用( )包起來呈現
例如節點的名稱叫做a01,這節點就是(a01)

每個節點之間可以有關係,就是用箭號的形式表達。
請發揮你的想像力,用簡單的ASCII字元聯想
--> 總共三個字元構成了一個箭號

一對一的關係,徐玄是少女時代的成員
(SeoHyun)-->(SNSD)
把徐玄指向少女時代就好

如果要表達一對多的關係呢?例如:徐玄跟Jessica都是少女時代的成員。
可以寫成兩個表達式
(SeoHyun)-->(SNSD),(Jessica)-->(SNSD)
甚至更直接,一個就夠了
(SeoHyun)-->(SNSD)<--(Jessica)


一個包含節點與關係的組合,稱為Path

標籤可以作為節點的標記,呈現方式是 :標籤名稱
例如 :SNSD
有一個叫做徐玄的節點,註記是少女時代:
(SeoHyun:SNSD)
使用標籤也是沒問題的,例如要多一個韓國人的標籤:
(SeoHyun:SNSD:Korean)

節點可以定義屬性,Neo4j裡面很像是一個JSON的表達方法。
屬性需要包在節點裡面,然後用大括號呈現。
例如一個節點徐玄,姓名Seo Hyun 性別是女。
然後生日部分,出生年是1991,日期6月28日。
在Neo4j的完整呈現方式如下(請容許我都翻成英文):
(SeoHyun {name:"Seo Hyun", gender:"female", year: 1991, date:"Jun.28"})

屬性的定義是為了日後的查詢操作。

節點跟節點之間原本沒有關係,可以讓他們發生關係。
並針對這個關係命名。
例如Jessica跟Crystal有姊妹的關係。
就可以這樣呈現 (Jessica)-[:SISTER]-(Crystal)

關係也可以是有向性的,例如Eric知道Jessica
因為Jessica是公眾人物,而阿宅我本人只是一個知道他的人。
Jessica並不知道我是誰 (如果知道了就好)
(Eric)-[:KNOWS]->(Jessica)

看得出來吧?基本上箭號那個線條就是兩個-構成 --
然後在中間插入[: 關係名稱] 就是有向的關係定義了

不若用來描述節點的標籤(label)可以有很多種
關係只能有一種,並沒有「開放式的交友關係」
所以可以用 | 來呈現多種關係的存在。

例如(Eric)-[:KNOWS|FANS_OF]->(Jessica)
語意上就是Eric知道Jessica或者說Eric是Jessica的粉絲。
關於關係的建立,該如何寫入資料庫中,之後說明。

當然,雙向關係也是可以的。
例如在夢中Jessica也認識Eric我本人。
(Eric)<-[:KNOWS]->(Jessica)


關係還有遠近之分,也就是有幾層?
現在就不要再舉少女時代的例子了,不然等等就被投訴
最實際的,就是朋友之間的關係。
我們生活中常常有以下對話:
「張三是那個我叫李四的朋友的朋友」
用Cypher表達節點與關係,就是
(Me)-->(李四)-->(張三)

這就是兩層的關係,可以用層級表達我跟張三的關係
(Me)->[*2]->(張三)

如果關係更複雜,想要表達我跟張三間3到5層的關係。
就是(Me)->[*3.. 5]->(張三)

表達3層以後的關係 (Me)->[*3.. ]->(張三)
表達小於5層的關係  (Me)->[*.. 5 ]->(張三)
表達任何曾的關係  (Me)->[*]->(張三)

套用到實際查詢上的語法範例:
MATCH (me)-[:KNOWS*1.. 2]-(friends)
WHERE me.name = "Eric"
RETURN friends.name

意義就是請Neo4j幫我找出跟我有認識的朋友關係
這邊定義了兩個臨時宣告的變數節點me還有friends
因為是變數,還要更明確的指出我的名字是Eric
所以有結合WHERE的條件與property是name要等於字串"Eric"
最後再回傳friends的節點名字

看得出來被指到friends的節點,應該都具備跟Eric節點類似的內容。
至少有name這個屬性就是了。

此外,整個「路徑」也可以用一個變數接受傳遞
例如 path = (me)-[*3.. 5]-(potential_friends)
在使用MATCH查詢時,最後如果是RETURN path
就會列出所有3到5層的關係

*******

這篇網誌還沒有講到更複雜的關係建立。
只是單純的介紹Neo4j的一些呈現形式。
建議先搞清楚({})這樣的節點跟屬性包裝,有助於後續的關係推廣。

原始的官方參考資料在這,覺得我寫的很爛請直接參考原文。


您也許同樣感興趣的文章:

Neo4j: Cypher語法筆記:一般表達形式 Expressions






Neo4j: Cypher語法筆記:表達形式 Expressions

The article described the expressions of Neo4j.

*******

Neo4j的Cypher語法支援了下面幾種表達形式。
如同多數的程式語言一樣,數字、字串、函數等方法都有支援。
以下是我簡單整理給自己看的,主要參考Neo4j的官方文件。

數字型態,主要是整數與小數,小數只支援到雙倍精確度(Double)
呈現時就是直接輸入數字,例如6, 7, 13, 12.05

字串 String,可以用單引號或者雙引號,夾帶長串的文字
"Eric Zero", 'Zero', "Neo4j"

變數,就是變數。英文習慣是Variable,但是官方文件說是identifier
可以是文字或者文字帶有數字,並且有區分大小寫。
在送出查詢使用時不用先宣告變數。
x, X, xYz, x1, 1xZ都可以,就是不能用單獨數字。
不然會被當成是一個數值內容。
每個物件本身會被視為一個物件。

屬性(Property),變數下的細節層級。
例如一個變數可以有長度或者名稱。
不要忘了,這個變數本身就是一個物件。
例如gene.name,指gene這個物件下面有一個名叫name的屬性。
gene.length,指gene下面還有length的屬性存在。
關於屬性,可能要自己建立一個資料節點(node)後比較有感。
這個之後再聊。

參數,用大括號包起來。
例如{param}、{0}

集合(collection of expression),使用中括號包裝。
裡面的元素用逗號區隔,集合內可以都是同樣型態的資料。
或者夾雜數字、字串、參數等混合。空集合也可以。
["a","b"]、[0,1,1.1,2]、["a2", 2,"test"]、[ ]

函數,跟多數程式語言一樣,用函數名與小括號。
括號裡面再放入輸入的物件,例如 length( str )

路徑表達 (path-pattern),實際上是「關係」的呈現為主。
這是Cypher很有特色的一點,用ASCII Art的方式呈現。
例如A指到B,就是(A)-->(B)
A跟C都指到B,可以用兩個方法呈現。
第一種:(A)-->(B) , (C)-->(B)
第二種:(A)-->(B)<--(C)

很有趣吧!包起來物件的左右小括號,看起來就跟圈圈一樣。
配合橫線跟大於等於的符號形成一個箭頭。

在語法表達式中,等號具備傳值的功能。
規則是右邊的值給左邊。
例如LengthOfSeq = seq.length
意思是LengthOfSeq這個變數的值,是來自於物件seq的length屬性。
length屬性如果是字串,LengthOfSeq收到後就是字串。
如果是Numerical, 收到後就是數值。

跳脫字元也是必要的,因為特殊字元需要特殊的處理方式。
有程式設計經驗的人都知道,Cypher也承襲多數語法慣例:
\t    Tab字元
\n   換行字元
\b   退位字元
\\    斜線
\'    單引號
\"   雙引號

跳脫字元 Escape Character的使用非常重要
尤其配合正規表示法(RegEx, Regular Expression)很普遍。

CASE,是一種條件表達式。符合條件的會被執行。
請看一下這個簡單的Cypher範例:

MATCH n
RETURN CASE  n.eyes
WHEN 'blue'
THEN 1
WHEN 'brown'
THEN 2
ELSE 3 END AS result


上面例子中,先找到資料節點n。
(MATCH等語法,另闢一文說明)
之後回傳n.eyes的屬性值作為CASE條件判斷用途
當值是字串blue傳回1,字串brown傳回2
其他都當作3(預設值),CASE到此結束以END表示
result這個值就是THEN的條件判斷後結果

*******

表達式的筆記先介紹到這裡,有錯誤煩請指教。

參考的原始官方網頁