golang 源碼分析:cayley-3-

        cayley 可以使用多種後端存儲,那麼如何使用 mysql 作爲後端存儲呢,首先我們看下如何配置:

store:
  # backend to use
  backend: mysql
  # address or path for the database
  address: "root:@tcp(localhost:3306)/cayley?loc=Local&charset=utf8mb4&collation=utf8mb4_general_ci"
  # open database in read-only mode
  read_only: false
  # backend-specific options
  options:
    nosync: false
query:
  timeout: 30s
load:
  ignore_duplicates: false
  ignore_missing: false
  batch: 10000

backend 設置成 mysql,並且指定 dsn 即可,接着我們使用 mysql 作爲後端存儲導入數據:

首先創建數據庫 cayley

% mysql.server start
Starting MySQL
.. SUCCESS!
 % mysql -uroot
Welcome to the MySQL monitor.  Commands end with ; or \g.
mysql> create database cayley;

初始化下看看是否成功

% ../cayley/cayley init -c cayley_example.yml
I0528 23:40:40.065734   81480 command.go:915] Cayley version: v0.8.x-dev (dev snapshot)
I0528 23:40:40.066011   81480 command.go:915] using config file: cayley_example.yml
I0528 23:40:40.066107   81480 database.go:71] using backend "mysql" (root:@tcp(localhost:3306)/cayley?loc=Local&charset=utf8mb4&collation=utf8mb4_general_ci)

檢查下,發現已經創建了兩個表

mysql> use cayley;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+------------------+
| Tables_in_cayley |
+------------------+
| nodes            |
| quads            |
+------------------+
2 rows in set (0.00 sec)

這兩個表分別存了頂點和四元祖

mysql> show create table nodes\G
*************************** 1. row ***************************
       Table: nodes
Create Table: CREATE TABLE `nodes` (
  `hash` binary(20) NOT NULL,
  `refs` int NOT NULL,
  `value` blob,
  `value_string` text,
  `datatype` text,
  `language` text,
  `iri` tinyint(1) DEFAULT NULL,
  `bnode` tinyint(1) DEFAULT NULL,
  `value_int` bigint DEFAULT NULL,
  `value_bool` tinyint(1) DEFAULT NULL,
  `value_float` double DEFAULT NULL,
  `value_time` datetime(6) DEFAULT NULL,
  PRIMARY KEY (`hash`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.02 sec)
show create table quads\G
*************************** 1. row ***************************
       Table: quads
Create Table: CREATE TABLE `quads` (
  `horizon` bigint unsigned NOT NULL AUTO_INCREMENT,
  `subject_hash` binary(20) NOT NULL,
  `predicate_hash` binary(20) NOT NULL,
  `object_hash` binary(20) NOT NULL,
  `label_hash` binary(20) DEFAULT NULL,
  `ts` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`horizon`),
  UNIQUE KEY `horizon` (`horizon`),
  UNIQUE KEY `spo_unique` (`subject_hash`,`predicate_hash`,`object_hash`),
  UNIQUE KEY `spol_unique` (`subject_hash`,`predicate_hash`,`object_hash`,`label_hash`),
  KEY `label_hash_fk` (`label_hash`),
  KEY `spo_index` (`subject_hash`,`predicate_hash`,`object_hash`),
  KEY `ops_index` (`object_hash`,`predicate_hash`,`subject_hash`),
  KEY `pos_index` (`predicate_hash`,`object_hash`,`subject_hash`),
  KEY `osp_index` (`object_hash`,`subject_hash`,`predicate_hash`),
  CONSTRAINT `label_hash_fk` FOREIGN KEY (`label_hash`) REFERENCES `nodes` (`hash`),
  CONSTRAINT `object_hash_fk` FOREIGN KEY (`object_hash`) REFERENCES `nodes` (`hash`),
  CONSTRAINT `predicate_hash_fk` FOREIGN KEY (`predicate_hash`) REFERENCES `nodes` (`hash`),
  CONSTRAINT `subject_hash_fk` FOREIGN KEY (`subject_hash`) REFERENCES `nodes` (`hash`)
) ENGINE=InnoDB AUTO_INCREMENT=314 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

導入數據

../cayley/cayley load -c cayley_example.yml -i ../cayley/data/**nq --alsologtostderr=true
I0528 23:43:00.003584   82856 command.go:915] Cayley version: v0.8.x-dev (dev snapshot)
I0528 23:43:00.006404   82856 command.go:915] using config file: cayley_example.yml
I0528 23:43:00.008158   82856 database.go:91] using backend "mysql" (root:@tcp(localhost:3306)/cayley?loc=Local&charset=utf8mb4&collation=utf8mb4_general_ci)

查看下存儲數據

mysql> select * from nodes limit 1\G
*************************** 1. row ***************************
        hash: 0x278A31F9BA54E8D73ADBC4F1AE82B1D2442DE516
        refs: 3
       value: NULL
value_string: NULL
    datatype: NULL
    language: NULL
         iri: NULL
       bnode: NULL
   value_int: NULL
  value_bool: 1
 value_float: NULL
  value_time: NULL
1 row in set (0.00 sec)

當然也可以開啓 http 服務來訪問 cayley

../cayley/cayley http -c cayley_example.yml --host=0.0.0.0:64210

瀏覽器打開 http://127.0.0.1:64210/,可以看到

那麼如何使用 go 來操作我們的圖數據庫呢

package main
import (
  "fmt"
  "log"
  "github.com/cayleygraph/cayley"
  _ "github.com/cayleygraph/cayley/graph/sql/mysql"
  "github.com/cayleygraph/quad"
)
func main() {
  // Create a brand new graph
  // store, err := cayley.NewGraph("sql", "root:@tcp(localhost:3306)/cayley?loc=Local&charset=utf8mb4&collation=utf8mb4_general_ci", nil)
  store, err := cayley.NewGraph("mysql", "root:@tcp(localhost:3306)/cayley?loc=Local&charset=utf8mb4&collation=utf8mb4_general_ci", nil)
  if err != nil {
    log.Fatalln(err)
  }
  store.AddQuad(quad.Make("phrase of the day", "is of course", "Hello World!", "label1"))
  store.AddQuad(quad.Make("Hello World!", "is of course", "Hello World1!", "label2"))
  store.AddQuad(quad.Make("Hello World1!", "is course", "Hello World2!", "label2"))
  // Now we create the path, to get to our data
  p := cayley.StartPath(store, quad.String("phrase of the day")).Out(quad.String("is of course")).Out(quad.String("is of course")).Out(quad.String("is course"))
  // Now we iterate over results. Arguments:
  // 1. Optional context used for cancellation.
  // 2. Flag to optimize query before execution.
  // 3. Quad store, but we can omit it because we have already built path with it.
  err = p.Iterate(nil).EachValue(nil, func(value quad.Value) {
    nativeValue := quad.NativeOf(value) // this converts RDF values to normal Go types
    fmt.Println(nativeValue)
  })
  if err != nil {
    log.Fatalln(err)
  }
}

運行下

% go run ./test/cayley/exp5/main.go
Hello World2!

        總結下,圖數據庫其實是圖到持久化存儲的一種遷移實現,我們知道圖有兩種數據結構可以來表示,鄰接表和鄰接矩陣。圖數據其實是鄰接矩陣的形式存儲的,同時利用了鄰接矩陣的稀疏性,存儲了訂單和邊,對應了兩個表 node 和 quad。實現上,圖數據庫有專用存儲和借用三方存儲兩種形式。cayley 是借用第三方存儲實現的。它在上層封裝了迭代器,並且封裝了 gizmo 查詢和 graphql 等,方便我們更加直觀處理圖相關邏輯。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/SHt_64kpVSnOd0-xogL2Ww