一.安裝
mkdir cayley
cd cayley
mkdir src
export GOPATH=$(pwd)
go get github.com/google/cayley
go build src/github.com/google/cayley/cayley.go
其中缺什麼包下什麼包,沒有hg工具安裝hg
修改下源碼cayley.go
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiYWan5SZk92Y5B3bj9CXzV2Zh1WavwVbvNmLzd2bsJmbj5ibv1WbvN2Lc9CX6MHc0RHaiojIsJye.gif)
switch cmd {
case "init":
db.Init(cfg, *tripleFile)
case "load":
ts, _ = db.Open(cfg)
db.Load(ts, cfg, *tripleFile)
ts.Close()
case "repl":
ts, _ = db.Open(cfg)
db.Repl(ts, *queryLanguage, cfg)
ts.Close()
case "http":
ts, _ := db.Open(cfg)
http.Serve(ts, cfg)
ts.Close()
default:
fmt.Println("No command", cmd)
flag.Usage()
}
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiYWan5SZk92Y5B3bj9CXzV2Zh1WavwVbvNmLzd2bsJmbj5ibv1WbvN2Lc9CX6MHc0RHaiojIsJye.gif)
運作
go build $GOPATH/src/github.com/google/cayley/cayley.go && ./cayley http --port=8080 --assets=$GOPATH/src/github.com/google/cayley --dbpath=src/testdata.nt
assets 參數代表啟動http server以後存放html靜态資源的目錄,源碼裡是自帶的
dbpath 是資料庫的一些初始化資料,必須指定,不然啟動了,也沒法添加資料,預設是指定為/tmp/testdb檔案
在浏覽器輸入http://127.0.0.1:8080/如果有頁面輸出說明成功了
二.基本概念
testdata.nt内容如下
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiYWan5SZk92Y5B3bj9CXzV2Zh1WavwVbvNmLzd2bsJmbj5ibv1WbvN2Lc9CX6MHc0RHaiojIsJye.gif)
alice follows bob .
bob follows alice .
charlie follows bob .
dani follows charlie .
dani follows alice .
alice is cool .
bob is "not cool" .
charlie is cool .
dani is "not cool" .
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiYWan5SZk92Y5B3bj9CXzV2Zh1WavwVbvNmLzd2bsJmbj5ibv1WbvN2Lc9CX6MHc0RHaiojIsJye.gif)
内容的每行都是以空格分隔的四元組,每一行叫做一個Triple,存儲多個Triple組成了TripleStore,每個Triple由四部分組成,依次對應資料每行用空格分隔的每項,分别叫Subject,Predicate,Object,Provenance。對應中文裡的,Subject是中文裡的主語,Predicate是中文裡的謂語,Object是賓語,Provenance是來源。也就是說,每行描述了,誰怎麼樣了XX,或者誰是XX樣的。Subject轉換成有向圖中的頂點,Object是出度的頂點,Predicate是路徑。
cayley搭了一套圖資料庫的架構,官方提供了三種存儲memory,leveldb,mongodb 可以切換存儲引擎,隻需要實作接口,就可以擴充存儲方式,和mysql與innodb的關系差不多。
三.使用API
1. g.V()
取一個圖中的頂點,也就是Triple中的Subject,傳回一個點的對象
2. path.Out( [predicatePath], [tags]
)
[predicatePath], [tags]
Out是取一個頂點的出度。不過,這個出度是按照謂詞區分的,當Out()不傳遞參數的時候,是取出某個頂點不按路徑區分的所有出度;當Out傳遞了
predicatePath
參數的時候,是取出某個頂點,在某個路徑上的所有出度。tags 是用來存儲路徑的名稱。例如:
我們入庫的資料中以alice頂點為例,
alice follows bob
alice is cool
可以看出alice這個頂點有兩個路徑,分别是follows和is
(1) 查詢allice的所有出度
g.V("alice").All()
(2) 查詢alice的關注:
g.V("alice").Out("follows").All()
(3) 查詢allice是否很cool
g.V("alice").Out("is").All()
(4) 查詢alice的關注和是否很cool
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiYWan5SZk92Y5B3bj9CXzV2Zh1WavwVbvNmLzd2bsJmbj5ibv1WbvN2Lc9CX6MHc0RHaiojIsJye.gif)
g.V("alice").Out(["follows", "is"]).All()
"result": [
{
"id": "bob"
},
{
"id": "cool"
}
]
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiYWan5SZk92Y5B3bj9CXzV2Zh1WavwVbvNmLzd2bsJmbj5ibv1WbvN2Lc9CX6MHc0RHaiojIsJye.gif)
(5) 雖然你可以直覺的看到,alice的關注是bob,并且alice是個很酷的人,那是因為是通過字面意思,比如有些人follows為空,有些人is為空,那就沒法判斷傳回的出度在哪個路徑上,這個時候應該使用tag參數
g.V("alice").Out(["follows", "is"], "path").All()
3. path.In( [predicatePath], [tags]
[predicatePath], [tags]
和Out正好相反,是求的入度。
(1) 求所有cool的人
g.V("cool").In("is").All()
(2) alice的粉絲
g.V("alice").In("follows").All()
4. path.Both( [predicatePath], [tags]
[predicatePath], [tags]
In和Out的的結果并集,沒有去重
5. path.Has( predicate, object
predicate, object
反向查找,paredicate是路徑,object是三元組中的賓語
(1) 查找alice的粉絲
g.V().Has("follows", "alice").All()
6.path.Follow(morphism)
通過管道加速
g.V().Has("name","Casablanca") .Out("/film/film/starring").Out("/film/performance/actor") .Out("name").All()
等價于
var filmToActor = g.Morphism().Out("/film/film/starring").Out("/film/performance/actor")
g.V().Has("name", "Casablanca").Follow(filmToActor).Out("name").All()
總體的查詢模式就是,選頂點,選路徑,ALL輸出
四. Triple,基于記憶體的TripleStore資料結構
1.資料結構
type Triple struct {
Subject string
Predicate string
Object string
Provenance string
}
三元組,Provenance好像是類似于資料庫裡的分庫的概念(不大确定),Triple中不同的字段,在後面叫Direction
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiYWan5SZk92Y5B3bj9CXzV2Zh1WavwVbvNmLzd2bsJmbj5ibv1WbvN2Lc9CX6MHc0RHaiojIsJye.gif)
type TripleStore struct {
idCounter int64 //idMap的長度
tripleIdCounter int64 //tripleId的序列
idMap map[string]int64 //存儲三元組的 内容->tripleId 的對應關系
revIdMap map[int64]string //存儲三元組的 tripleId->内容 的對應關系 idMap的反向映射關系
triples []graph.Triple //存儲每條記錄的關系三元組
size int64 //triples的數量
index TripleDirectionIndex //triples的索引 每個idMap中的一個key有一個平衡二叉樹,裡面放了tripleId
}
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiYWan5SZk92Y5B3bj9CXzV2Zh1WavwVbvNmLzd2bsJmbj5ibv1WbvN2Lc9CX6MHc0RHaiojIsJye.gif)
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiYWan5SZk92Y5B3bj9CXzV2Zh1WavwVbvNmLzd2bsJmbj5ibv1WbvN2Lc9CX6MHc0RHaiojIsJye.gif)
TripleDirectionIndex是一個通過Direction作為分組的一級索引
type TripleDirectionIndex struct {
subject map[int64]*llrb.LLRB
predicate map[int64]*llrb.LLRB
object map[int64]*llrb.LLRB
provenance map[int64]*llrb.LLRB
}
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiYWan5SZk92Y5B3bj9CXzV2Zh1WavwVbvNmLzd2bsJmbj5ibv1WbvN2Lc9CX6MHc0RHaiojIsJye.gif)
2.執行個體示範
資料
alice follows bob .
bob follows alice .
charlie follows bob .
建立以後的結果如下
idMap revIdMap
1 <=============> alice
2 <=============> follows
3 <=============> bob
4 <=============> charlie
triples
Direction DirectionSubject DirectionPredicate DirectionObject
tripleId 1 alice follows bob
2 bob follows alice
3 charlie follows bob
DirectionIndex
1 =========> (1)
DirectionSubject=============> 3 =========> (2)
4 =========> (3)
DirectionPredicate============> 2 =========> 插入第一行時(1) ---> 插入第二行 (2) /
(1)
-----> 插入第三行 (2)
/ \
(1) (3)
DirectionObject==============> 3 ============> 插入第一行 (1) ---> 插入第三行 (3)
/
(1)
1 =============> (2)
DirectionIndex中的1 是IdMap中的編号,(1)是triples中的tripleId
3.查詢方法
看源碼裡把查詢邏輯都寫在了itorator裡,各種hasA,and,or,link!@#!4。
如果查一個值的入度就是先查DirectionObject索引,查出度就查DirectionSubject索引,有路徑條件就再在DirectionPredicate裡做二分排除掉。
原文位址:https://www.cnblogs.com/23lalala/p/3865485.html