之前在解釋基本查詢的運作時,提到了
用
[?e :person/name "Ridley Scott"]
這個條件比對整個資料庫的內容,:where
子句裡的?e
是一個未知的變數。
這邊,我們多定義一些詞彙以讓日後的用語更精確。
[?e :person/name "Ridley Scott"]
這種出現在 :where
之後的向量,稱之為資料模式。[E A V Tx]
的向量。另一方面,很多時候,我們並不在意 Tx
的值,所以寫資料模式時,常常也只寫 [E A V]
。來看一個比較複雜的查詢:
[:find ?title
:where
[?e :movie/year 1987]
[?e :movie/title ?title]]
這個查詢是要找出,所有 1987 年的電影的名稱 (title)。這邊有兩點值得注意:
?e
。
[:find ?title
:where
[?e :movie/title ?title]
[?e :movie/year 1987]]
上述的查詢如果改寫成對應的 SQL 的話:
SELECT title
FROM movie
WHERE year = 1987;
如果我們想查的是:「誰主演了 "Lethal Weapon" 這部電影?」可以寫成如下的查詢:
[:find ?name
:where
[?m :movie/title "Lethal Weapon"]
[?m :movie/cast ?p]
[?p :person/name ?name]]
資料模式的部分,可以理解成:
[?m :movie/title "Lethal Weapon"]
?m
應綁定的值。[?m :movie/cast ?p]
?m
的值的前提之下,可以推得人的實體編碼 ?p
[?p :person/name ?name]
?p
的值的前提之下,可以推得人的名字 ?name
上述的查詢如果改寫成對應的 SQL 的話:
SELECT person.name
FROM movie
INNER JOIN person
ON movie.cast = person.id
WHERE movie.title = "Lethal Weapon";
不知道大家有沒有發現, inner join
在不知不覺中就已經發生了。
註:
下方的查詢要找出有演出過電影、且叫做 "Clinton Eastwood" 的人的實體編碼 (entity id)。
[:find ?p
:where
[_ :movie/cast ?p]
[?p :person/name "Clinton Eastwood"]]
因為需要確保,這個人有演出過電影,所以需要寫 [_ :movie/cast ?p]
,但我們並不在意是哪部電影,有就好,這時就使用底線去佔據這個資料模式裡的 E
的位置。