查詢語言
Dgraph的GraphQL+-是一種基于facebook的GraphQL的圖查詢語言丧没。GraphQL并不是專門用于圖數(shù)據(jù)庫的,但是它像圖一樣的查詢語法漆际,schema驗證以及子圖形式的response使它成為一個非常好的語言選擇奸汇。我們修改了這個語言擂找,并且移除了某些feature浩销,使它可以更好地支持圖操作撼嗓,更好地適用于圖數(shù)據(jù)庫,并將新的語言命名為“GraphQL+-”
GraphQL+-還在繼續(xù)改進且警,我們在添加更多的feature,將來也會簡化某些已有的feature
1. GraphQL+-基礎(chǔ)
一個GraphQL+-查詢會基于查詢規(guī)范在圖中進行匹配肩刃,并返回一個圖作為結(jié)果
查詢從查詢root開始盈包,由嵌套塊組成呢燥。root會找到初始的node集合叛氨,供后面的匹配及過濾用
1.1.1 返回值
每個查詢都有名字寞埠,由查詢的root指定仁连,查詢結(jié)果也會使用這個名字
2.Facets:邊屬性
Dgraph支持facets(邊上的鍵值對)饭冬,來作為RDF三元組的擴展。Facets可以將屬性添加到邊上,而不是節(jié)點上扰魂。例如劝评,兩個人之間的friend邊可以加上close屬性蒋畜,來標識友誼是否終結(jié)姻成。Facets也可以用作邊的權(quán)重
盡管你可能會學過很多遍facets科展,你還是可能會用錯才睹。例如你不應該給friend邊加上date_of_birth這樣的facet琅攘,而應該加上start_of_friendship這樣的facet
注意坞琴,F(xiàn)acet不是Dgraph的第一公民
Facet的key是string
置济,value可以是string
, bool
, int
, float
或者 dateTime
浙于。對于int與float羞酗,只能是32位有符號的decimial interger檀轨,以及64位單浮點值
下面的mutation在mobile以及car上加了名為since的facet参萄,記錄Alice買車以及開始用這個手機號的時間
首先添加schema:
//ALTER
name: string @index(exact, term) .
rated: uid @reverse @count .
插入數(shù)據(jù):
//MUTATE
{
set {
# -- Facets on scalar predicates
_:alice <name> "Alice" .
_:alice <mobile> "040123456" (since=2006-01-02T15:04:05) .
_:alice <car> "MA0123" (since=2006-02-02T13:01:09, first=true) .
_:bob <name> "Bob" .
_:bob <car> "MA0134" (since=2006-02-02T13:01:09) .
_:charlie <name> "Charlie" .
_:dave <name> "Dave" .
# -- Facets on UID predicates
_:alice <friend> _:bob (close=true, relative=false) .
_:alice <friend> _:charlie (close=false, relative=true) .
_:alice <friend> _:dave (close=true, relative=true) .
# -- Facets for variable propagation
_:movie1 <name> "Movie 1" .
_:movie2 <name> "Movie 2" .
_:movie3 <name> "Movie 3" .
_:alice <rated> _:movie1 (rating=3) .
_:alice <rated> _:movie2 (rating=2) .
_:alice <rated> _:movie3 (rating=5) .
_:bob <rated> _:movie1 (rating=5) .
_:bob <rated> _:movie2 (rating=5) .
_:bob <rated> _:movie3 (rating=5) .
_:charlie <rated> _:movie1 (rating=2) .
_:charlie <rated> _:movie2 (rating=5) .
_:charlie <rated> _:movie3 (rating=1) .
}
}
2.1 標量謂語(value邊)上的facet
查詢Alice的name讹挎、mobile以及car返回的結(jié)果與沒有facet是一樣的
{
alice(func: eq(name,"Alice")){
name
mobile
car
}
}
語法@facets(facet-name)
用于查詢facet數(shù)據(jù)筒溃,Alice的since
facet應該按如下的方式查詢:
{
data(func: eq(name, "Alice")) {
name
mobile @facets(since)
car @facets(since)
}
}
返回結(jié)果:
{
"data": {
"data": [
{
"name": "Alice",
"mobile|since": "2006-01-02T15:04:05Z",
"mobile": "040123456",
"car|since": "2006-02-02T13:01:09Z",
"car": "MA0123"
}
]
}
}
Facet會在相應邊的統(tǒng)一level返回浑测,key的格式是edgename|facetname
如果要查詢某個邊上的所有facet迁央,使用@facets
不加參數(shù)即可:
{
data(func: eq(name, "Alice")) {
name
mobile @facets
car @facets
}
}
2.2 Facet的別名
在查詢某個謂語時滥崩,可以指定別名夭委,格式類似于請求其他謂語的別名株灸。orderasc
與 orderdesc
不能用作別名慌烧,因為它們有特別意義屹蚊,其他的任何字符串都能用作別名
在這里,我們給分別給since
, close
兩個facet設置別名car_since
, close_friend
{
data(func: eq(name, "Alice")) {
name
mobile
car @facets(car_since: since)
friend @facets(close_friend: close) {
name
}
}
}
2.3 UID謂語(uid邊)的facet
UID邊上的域名類似于value邊
例如田晚,friend
是有一個名為close
的facet的邊
查詢friend邊的close facet:
{
data(func: eq(name, "Alice")) {
name
friend @facets(close) {
name
}
}
}
對于像friend這種的uid邊贤徒,facet會進入edge|facet下面相應的子節(jié)點接奈。上面的例子中你會看到,Alice與Bob之間的friend|close與Bob的結(jié)果出現(xiàn)在一起:
{
"data": {
"data": [
{
"name": "Alice",
"friend": [
{
"name": "Charlie",
"friend|close": false
},
{
"name": "Dave",
"friend|close": true
},
{
"name": "Bob",
"friend|close": true
}
]
}
]
}
}
Bob有一輛車互捌,并且這個車有一個名為since
的facet,在下面的例子中我們可以看到car|since也是在Bob的屬性里:
{
data(func: eq(name, "Alice")) {
name
friend @facets {
name
car @facets
}
}
}
{
"data": {
"data": [
{
"name": "Alice",
"friend": [
{
"name": "Charlie",
"friend|close": false,
"friend|relative": true
},
{
"name": "Dave",
"friend|close": true,
"friend|relative": true
},
{
"name": "Bob",
"car|since": "2006-02-02T13:01:09Z",
"car": "MA0134",
"friend|close": true,
"friend|relative": false
}
]
}
]
}
}
2.4 在Facet上過濾
Dgraph支持基于facet過濾邊硼讽,過濾方式類似于沒有facet但是有與facet同名的函數(shù)
找到Alice已經(jīng)close的friend:
{
data(func: eq(name, "Alice")) {
friend @facets(eq(close, true)) {
name
}
}
}
如果要在filter的同時返回facet固阁,再加上 @facets(<facetname>)
即可:
{
data(func: eq(name, "Alice")) {
friend @facets(eq(close, true)) @facets(relative) { # filter close friends and give relative status
name
}
}
}
Facet查詢也可以使用AND
, OR
以及 NOT
組合起來:
{
data(func: eq(name, "Alice")) {
friend @facets(eq(close, true) AND eq(relative, true)) @facets(relative) { # filter close friends in my relation
name
}
}
}
2.5 使用facet排序
可以使用uid邊上的facet排序。下面我們把Alice并齐、Bob以及Charlie各自對電影的評分對電影進行排序:
{
me(func: anyofterms(name, "Alice Bob Charlie")) {
name
rated @facets(orderdesc: rating) {
name
}
}
}
2.6 將facet的值賦給變量
UID邊上的facet可以以邊到facet值的映射的格式保存到值變量里
{
var(func: eq(name, "Alice")) {
friend @facets(a as close, b as relative)
}
friend(func: uid(a)) {
name
val(a)
}
relative(func: uid(b)) {
name
val(b)
}
}
2.7 Facet與值傳播
Facet的int况褪、float類型的值可以被賦給變量测垛,這就是值傳播(values propagate)
Alice食侮、Bob以及Charlie每個人都對每個電影評了分锯七,一個facetrating
上的值變量保存了從電影到評分的映射起胰。查詢可以從多條路徑到達一個電影效五,并將每條路徑上的評分加起來畏妖。下面的查詢就把Alice戒劫、Bob迅细、Charlie對三個電影的評分加起來了:
{
var(func: anyofterms(name, "Alice Bob Charlie")) {
num_raters as math(1)
rated @facets(ra as rating) { #這里ra直接就是三人對每部電影的評分總和map
#total_rating as math(ra) total_rating跟ra時等價的
avg_rating as math(ra/num_raters)S
}
}
data(func: uid(ra)) {
name
total_rating : val(ra)
avg_rating : val(avg_rating)
}
}
2.8 Facet與聚合
賦給值變量的Facet是可以被聚合的
{
data(func: eq(name, "Alice")) {
name
rated @facets(r as rating) {
name
}
avg(val(r))
}
}
注意茵典,因為r是每部電影到其總評分的映射,所以下面的想要分別計算Alice與Bob各自對所有電影的平均評分的查詢語句是錯誤的:
{
data(func: anyofterms(name, "Alice Bob")) {
name
rated @facets(r as rating) {
name
}
avg(val(r))
}
}
計算每個用戶對電影的平均評分需要一個映射用戶到他們各自的評分的變量:
{
var(func: has(~rated)) {
num_rated as math(1)
~rated @facets(r as rating) {#關(guān)鍵是這里春宣,反向邊可以獲得每個人對所有電影的總評分
avg_rating as math(r / num_rated)
}
}
data(func: uid(avg_rating)) {
name
val(avg_rating)
}
}
3. K-最短路徑查詢
4. 遞歸查詢
遞歸查詢讓你遍歷一系列謂語(通過filter、facet等)哥谷,直到到達所有葉子節(jié)點呼巷,或者到達depth
參數(shù)寫的最大深度
為了獲得某個有30000部電影的題材下的十部電影王悍,并獲取這些電影中的兩個演員压储,我們可以做如下查詢:
{
me(func: gt(count(~genre), 30000), first: 1) @recurse(depth: 1, loop: true) {
uid
name@en
~genre (first:3) @filter(gt(count(starring), 2)) #十個太多集惋,三個
starring (first: 2)
performance.actor
}
}
#這個查詢的root是個genre刮刑,但是下面的starring雷绢、performance.actor顯然不是genre的謂語翘紊,這就是遞歸的意思
使用遞歸查詢時注意:
- 在root之后只能指定一層謂語帆疟。這些會被遞歸查詢踪宠。標量與節(jié)點都會被當作類似的
- 每個查詢只建議有一個遞歸block
- 小心結(jié)果集可能會快速膨脹柳琢,如果結(jié)果集太大的話染厅,會報錯肖粮。在這種情況下使用更多的filter涩馆、使用分頁限制條數(shù)魂那,或者像上面一樣提供一個深度參數(shù)
上面的遞歸查詢在depth不同的時候,返回結(jié)果時不同的
- depth=1活逆,查詢到genre
{
"data": {
"me": [
{
"uid": "0x1de841",
"name@en": "Drama"
}
]
}
}
- depth=2蔗候,genre->movie
{
"data": {
"me": [
{
"uid": "0x1de841",
"name@en": "Drama",
"~genre": [
{
"uid": "0x17",
"name@en": "House of Boys"
},
{
"uid": "0x1e",
"name@en": "U raskoraku"
},
{
"uid": "0x38",
"name@en": "I Want You"
}
]
}
]
}
}
- depth=3锈遥,genre->movie->starring
{
"data": {
"me": [
{
"uid": "0x1de841",
"name@en": "Drama",
"~genre": [
{
"uid": "0x17",
"name@en": "House of Boys",
"starring": [
{
"uid": "0x1622f"
},
{
"uid": "0x38fa9"
}
]
},
{
"uid": "0x1e",
"name@en": "U raskoraku",
"starring": [
{
"uid": "0x2a1d57"
},
{
"uid": "0x2f7e3a"
}
]
},
{
"uid": "0x38",
"name@en": "I Want You",
"starring": [
{
"uid": "0xa6775"
},
{
"uid": "0xad95f"
}
]
}
]
}
]
}
}
- depth=4丽惶,genre->movie->starring->performance.actor
{
"data": {
"me": [
{
"uid": "0x1de841",
"name@en": "Drama",
"~genre": [
{
"uid": "0x17",
"name@en": "House of Boys",
"starring": [
{
"uid": "0x1622f",
"performance.actor": [
{
"uid": "0x5352a1",
"name@en": "Marco Wirges"
}
]
},
{
"uid": "0x38fa9",
"performance.actor": [
{
"uid": "0x2c7490",
"name@en": "Mohamed Moulouaa"
}
]
}
]
},
{
"uid": "0x1e",
"name@en": "U raskoraku",
"starring": [
{
"uid": "0x2a1d57",
"performance.actor": [
{
"uid": "0x1d9bd8",
"name@en": "Danilo Stojkovi?"
}
]
},
{
"uid": "0x2f7e3a",
"performance.actor": [
{
"uid": "0x836ab7",
"name@en": "Jovan-Burdus Janicijevic"
}
]
}
]
},
{
"uid": "0x38",
"name@en": "I Want You",
"starring": [
{
"uid": "0xa6775",
"performance.actor": [
{
"uid": "0x97dd22",
"name@en": "Antonio Velázquez"
}
]
},
{
"uid": "0xad95f",
"performance.actor": [
{
"uid": "0x29824",
"name@en": "Cristina Plazas"
}
]
}
]
}
]
}
]
}
}
- depth=5懦尝,genre->movie->starring->performance.actor陵霉,查詢結(jié)果跟depth=4一樣
5. Fragments
fragment
關(guān)鍵詞允許你定義新的可以被查詢引用的fragment踊挠,像GraphQL specification一樣效床。如果有多個部分需要查詢相同的字段剩檀,可以定義一個fragment沪猴,并多次調(diào)用它运嗜。Fragment可以被嵌套担租,但是不可以組成環(huán)。示例如下:
curl localhost:8080/query -XPOST -d $'
query {
debug(func: uid(1)) {
name@en
...TestFrag
}
}
fragment TestFrag {
initial_release_date
...TestFragB
}
fragment TestFragB {
country
}' | python -m json.tool | less
6. GraphQL變量
7. 用自定義Tokenizers分詞
8. 函數(shù)
9. 連接Filter
10. 別名
11. 分頁
12. Count
13. 排序
14. 多查詢塊
15. 查詢變量
16. 值變量
17. 聚合
18. 值變量上的Math
19. GroupBy
20. Expand Predicates
21. Cascade命令
22. Normalize命令
23. Debug
24. Schema
對每個謂語來說,schema指定它的目標的類型承璃。如果一個謂語p
的類型為T
盔粹,那么對于所有的主-謂-賓三元組舷嗡,賓語的類型都是T
- 在mutation時进萄,會檢查標量類型中鼠,并且在當這個值不能轉(zhuǎn)為schema里的類型時會報錯
- 在查詢時援雇,值類型會根據(jù)schema中謂語的類型返回
如果在執(zhí)行插入一個triple的mutation時沒有在schema中添加謂語類型惫搏,那么會根據(jù)第一個mutation推斷類型,這些類型包括:
-
uid
茴丰,如果某個謂語的第一個mutation的主語跟賓語都是node - 根據(jù)rdf type派生较沪,如果賓語是一個字面量,而且第一個mutation中有rdf type
- 其他的都是
default
類型
24.1 Schema Type
Dgraph支持標量類型萄焦,以及uid類型
24.1.1 標量類型
對于所有的謂語是標量類型的三元組拂封,賓語是字面量
Dgraph Type | Go type |
---|---|
default |
string |
int |
int64 |
float |
float |
string |
string |
bool |
bool |
dateTime |
time.Time (RFC3339 format [Optional timezone] eg: 2006-01-02T15:04:05.999999999+10:00 or 2006-01-02T15:04:05.999999999) |
geo |
go-geom |
password |
string (encrypted) |
24.1.2 UID類型
uid
類型表示一個node到node的邊在抛,在Dgraph內(nèi)部刚梭,每個node都用一個uint64
類型的id表示
Dgraph Type | Go type |
---|---|
uid |
uint64 |
24.2 添加或修改Schema
Schema mutation可以添加或者修改schema
如果某個謂語you多個標量值也可以通過指定一個類型list,使用一個S P
添加衅金。下面這個例子中的occupations可以為每個S P
保存一個字符串list
可以使用@index
指定索引類型氮唯,并且可以通過參數(shù)指定tokenizer您觉。當給一個謂語指定index之后琳水,必須給這個index指定類型。例如:
name: string @index(exact, fulltext) @count .
age: int @index(int) .
friend: uid @count .
dob: dateTime .
location: geo @index(geo) .
occupations: [string] @index(term) . #occupations的值是一個string數(shù)組
如果某個謂語沒存數(shù)據(jù)私沮,一個schema mutation會建立一個空的schema準備接收三元組仔燕。
如果在mutation之前已經(jīng)有數(shù)據(jù)了晰搀,已有的數(shù)據(jù)不會被核對來遵從新的schema外恕。但是在查詢時罪郊,Dgraph會試圖將已有的數(shù)據(jù)轉(zhuǎn)化為新的schema中的類型悔橄,并且會忽略任何轉(zhuǎn)換錯誤
忽略錯誤好像會導致查詢時出現(xiàn)某些很異常的問題橄维,比如某些謂語會丟失
如果已經(jīng)有數(shù)據(jù)拴曲,但是制定了新的index類型争舞,那么任何原有的但是不在更新后的index類型列表中的inde都會被丟棄,新的index類型會自動被創(chuàng)建
如果在schema mutation的時候指定了反向邊澈灼,它也會被計算出來
24.3 RDF類型
在mutation的時候竞川,Dgraph支持多種RDF類型
除了在執(zhí)行第一個mutation的時候隱式推斷類型,RDF類型還可以覆蓋保存的schema
如果一個謂語在schema中一個類型叁熔,而一個mutation中的RDF含有不同Dgraph底層數(shù)據(jù)類型,轉(zhuǎn)換到schema中的type時拋出了不兼容的異常荣回,但是值被存儲為RDF中的類型相應的Dgraph類型遭贸。查詢結(jié)果通常會以schema中的類型返回
例如,如果age這個謂語沒有在schema中設置類型心软,執(zhí)行下面的mutation:
{
set {
_:a <age> "15"^^<xs:int> .
_:b <age> "13" .
_:c <age> "14"^^<xs:string> .
_:d <age> "14.5"^^<xs:string> .
_:e <age> "14.5" .
}
}
然后查詢:
{
fgggg(func: has(age)){
expand(_all_)
}
}
報錯:
: strconv.ParseInt: parsing "14.5": invalid syntax
Dgraph:
- 根據(jù)第一個三元組的隱式轉(zhuǎn)換壕吹,將schema類型設置為
int
- 將保存的
13
載存儲中轉(zhuǎn)換成int
- 檢查發(fā)現(xiàn)
14
可以被轉(zhuǎn)換成int,但是會按string
存儲 - 最后兩個三元組會報錯删铃,因為
14.5
不能被轉(zhuǎn)換成int
24.4 擴展類型
24.4.1 Password類型
可以在schema中使用password
類型給一個實體設置密碼耳贬。不能直接查詢密碼,只能使用checkpwd
函數(shù)來判斷一個密碼是否匹配
首先猎唁,定義schema:
//alter
pass: password .
然后設置密碼:
#mutate
{
set {
<0x123> <name> "Password Example"
<0x123> <pass> "ThePassword" .
}
}
檢查密碼:
#query
{
check(func: uid(0x123)) {
name
checkpwd(pass, "ThePassword")
}
}
輸出:
{
"check": [
{
"name": "Password Example",
"pass": [
{
"checkpwd": true
}
]
}
]
}
24.5 索引
當使用函數(shù)進行過濾的時候咒劲,Dgraph會使用索引讓大數(shù)據(jù)集的索引更高效
所有的標量類型都可以被索引
int
, float
, bool
以及 geo
都只有一個默認索引類型,tokenizers的名字依次為 int
, float
, bool
與geo
而string與dateTime類型有多個索引類型
24.5.1 string索引
string類型有如下索引類型:
Dgraph function | Required index / tokenizer | Notes |
---|---|---|
eq |
hash , exact , term , or fulltext
|
對于 eq 函數(shù)來說性能最好的索引類型是 hash . 只有相似需要eq 的同時還需要全文檢索的時候诫隅,再考慮使用 term 或 fulltext 索引腐魂。如果已經(jīng)在用term 了,那就無需再用hash 或exact 了 |
le , ge , lt , gt
|
exact |
允許快速排序 |
allofterms , anyofterms
|
term |
允許根據(jù)語句中的一個項進行查詢 |
alloftext , anyoftext
|
fulltext |
通過指定的詞干以及停止詞匹配語言 |
regexp |
trigram |
正則表達式匹配逐纬,也可以用于相等驗證 |
警告
不正確的index選擇可能會極大地增加性能負載蛔屹,并且提高事務沖突的概率。盡量只使用最少的风题、最簡單的索引類型
24.5.2 DateTime索引
下列索引類型適用于dateTime類型:
Index name / Tokenizer | Part of date indexed |
---|---|
year |
對年建索引(默認) |
month |
對年判导、月建索引 |
day |
對年、月沛硅、日建索引 |
hour |
對年眼刃、月、日摇肌、小時建索引 |
24.5.3 可排序索引
不是所有的索引都會給所有的值建立一個排序擂红。可排序的索引允許執(zhí)行不等函數(shù)以及排序
-
int
與float
索引是可排序的 -
string
類型的exact
索引是可排序的 - 所有的
dateTime
索引是可排序的
例如围小,對于string類型的name邊昵骤,為了對name進行排序以對它執(zhí)行不等過濾,必須指定exact
索引類型肯适。這種情況下schema查詢將返回至少返回下面的內(nèi)容:
{
"predicate": "name",
"type": "string",
"index": true,
"tokenizer": [
"exact"
]
}
24.5.4 Count索引
對于帶有@count
的謂語变秦,Dgraph會對每個節(jié)點的出邊數(shù)建立索引。這可以使下面這種查詢變的更快:
{
q(func: gt(count(pred), threshold)) {
...
}
}
24.5 List類型
標量類型的謂語也可以存儲值list框舔。標量類型需要使用[]
包起來蹦玫,表明它是一個list類型,這些list使無序的集合
occupations: [string] .
score: [int] .
- set操作可以向list中添加一個值刘绣。值的順序不能保證
- delete操作可以從list中刪除一個值
- 對這些謂語的查詢將按數(shù)組的格式返回list
- 索引可以被應用于值為list的謂語樱溉,你也可以在它們上執(zhí)行函數(shù)
- 這些謂語不能進行排序
24.6 反向邊
圖的邊是單向的。對于節(jié)點到節(jié)點的邊纬凤,有時需要構(gòu)建反向福贞。只要某個主-謂-賓三元組需要一個反向邊,手動添加即可停士。如果某個謂語都會有一個反向挖帘,只要在schema中指定@reverse
,Dgraph就會自動計算出反向邊
anEdge
的反向邊是~anEdge
對于已有的數(shù)據(jù)恋技,Dgraph會計算所有的反向邊肠套。對于在schema修改之后新添加的數(shù)據(jù),Dgraph會為每個新加的三元組計算并添加反向邊
24.7 查詢schema
查詢所有的schema:
schema { }
查詢特定的字段:
schema {
type
index
reverse
tokenizer
}
查詢特定謂語:
schema {
type
index
reverse
tokenizer
}
25. Mutation
添加或移除數(shù)據(jù)被稱作mutation
一個添加三元組的mutation使用set
關(guān)鍵詞添加數(shù)據(jù):
{
set {
# triples in here
}
}
25.1 Triple
輸入的語言是遵循W3C格式的 RDF N-Quad format三元組
triple的格式如下:
<subject> <predicate> <object>
意味著以subject
為標志的圖節(jié)點通過有向邊predicate
連接到object
猖任。每個triple以一個句號(full stop)結(jié)尾你稚。triple中的subject一定是圖中的一個節(jié)點,而object可以是一個node也可以是一個value
例如朱躺,下面的triple:
<0x01> <name> "Alice" .
表示uid為0x01
的節(jié)點有一個string類型的name
刁赖,值為“Alice”。而下面的triple:
<0x01> <friend> <0x02> .
表示uid為0x01
的節(jié)點通過friend
邊連接到0x02
Dgraph會為每個節(jié)點創(chuàng)建一個唯一的64位識別符——uid长搀。一個mutation要么使用空節(jié)點或外部id節(jié)點(blank or external id nodes)讓Dgraph為subject或者object創(chuàng)建uid宇弛,或者指定一個之前的mutation創(chuàng)建的uid
25.2 空節(jié)點與uid
mutation中的空節(jié)點寫作_:identifier
,標志mutation內(nèi)部的節(jié)點源请。Dgraph會為每個空節(jié)點創(chuàng)建一個uid枪芒,并將它作為mutation的結(jié)果返回彻况。例如,下面的mutation:
{
set {
_:class <student> _:x .
_:class <student> _:y .
_:class <name> "awesome class" .
_:x <name> "Alice" .
_:x <planet> "Mars" .
_:x <friend> _:y .
_:y <name> "Bob" .
}
}
返回的結(jié)果:
{
"data": {
"code": "Success",
"message": "Done",
"uids": {
"class": "0x2712",
"x": "0x2713",
"y": "0x2714"
}
}
}
圖被更新后舅踪,就仿佛儲存如下的triple:
<0x6bc818dc89e78754> <student> <0xc3bcc578868b719d> .
<0x6bc818dc89e78754> <student> <0xb294fb8464357b0a> .
<0x6bc818dc89e78754> <name> "awesome class" .
<0xc3bcc578868b719d> <name> "Alice" .
<0xc3bcc578868b719d> <planet> "Mars" .
<0xc3bcc578868b719d> <friend> <0xb294fb8464357b0a> .
<0xb294fb8464357b0a> <name> "Bob" .
空節(jié)點標簽_:class
纽甘、_:x
以及_:
在mutation執(zhí)行之后不能再涌來識別節(jié)點,也不會存儲在dgraph中抽碌,下一個mutation一樣可以復用它們
后續(xù)的mutation可以更新已有的uid的數(shù)據(jù)悍赢。例如,下面的mutation向class中添加了一個新學生:
{
set {
<0x6bc818dc89e78754> <student> _:x .
_:x <name> "Chris" .
}
}
25.3 外部id
Dgraph的輸入語言是RDF货徙,它還支持<a_fixed_identifier> <predicate> literal/node
格式的triple左权,這里的標簽a_fixed_identifier
會被當作這個node的唯一識別符。例如痴颊,混合schema.org識別符赏迟、the movie database識別符以及空節(jié)點:
_:userA <http://schema.org/type> <http://schema.org/Person> .
_:userA <http://schema.org/name> "FirstName LastName" .
<https://www.themoviedb.org/person/32-robin-wright> <http://schema.org/type> <http://schema.org/Person> .
<https://www.themoviedb.org/person/32-robin-wright> <http://schema.org/name> "Robin Wright" .
0.8版本的Dgraph沒有原生支持這樣的外部id作為節(jié)點的識別符,外部id可以以xid
邊的形式作為node的屬性存儲下來蠢棱。例如瀑梗,上面的謂語在Dgraph中是有效的,但是節(jié)點http://schema.org/Person在Dgraph中是以一個uid來識別的裳扯,比方說0x123
抛丽,它會有如下的一個邊:
<0x123> <xid> "http://schema.org/Person" .
而Robin Wright可能有uid0x321
,以及triple:
<0x321> <xid> "https://www.themoviedb.org/person/32-robin-wright" .
<0x321> <http://schema.org/type> <0x123> .
<0x321> <http://schema.org/name> "Robin Wright" .
一個合適的schema可能是:
xid: string @index(exact) .
<http://schema.org/type>: uid @reverse .
查詢舉例:
{
var(func: eq(xid, "http://schema.org/Person")) {
allPeople as <~http://schema.org/type>
}
q(func: uid(allPeople)) {
<http://schema.org/name>
}
}
查詢舉例饰豺,通過外部id查找Eobin Wright:
{
robin(func: eq(xid, "https://www.themoviedb.org/person/32-robin-wright")) {
expand(_all_) { expand(_all_) }
}
}
注意
xid
邊不會在mutation的時候自動添加亿鲜。用戶需要自己判斷某個xid
是否存在,并添加節(jié)點及xid
邊
25.4 語言與RDF類型
RDF N-Quad允許給一個字符串值指定語言類型以及一個RDF類型冤吨,語言通過@lang
指定蒿柳,例如:
<0x01> <name> "Adelaide"@en .
<0x01> <name> "Аделаида"@ru .
<0x01> <name> "Adéla?de"@fr .
RDF類型通過標準的^^
分隔符附在字面量上,像這樣:
<0x01> <age> "32"^^<xs:int> .
<0x01> <birthdate> "1985-06-08"^^<xs:dateTime> .
支持的RDF datatypes以及相關(guān)的內(nèi)部類型以及相關(guān)的內(nèi)部類型如下:
Storage Type | Dgraph type |
---|---|
<xs:string> | string |
<xs:dateTime> | dateTime |
<xs:date> | datetime |
<xs:int> | int |
<xs:boolean> | bool |
<xs:double> | float |
<xs:float> | float |
geo:geojson | geo |
http://www.w3.org/2001/XMLSchema#string | string |
http://www.w3.org/2001/XMLSchema#dateTime | dateTime |
http://www.w3.org/2001/XMLSchema#date | dateTime |
http://www.w3.org/2001/XMLSchema#int | int |
http://www.w3.org/2001/XMLSchema#boolean | bool |
http://www.w3.org/2001/XMLSchema#double | float |
http://www.w3.org/2001/XMLSchema#float | float |
參閱章節(jié)RDF schema types來理解RDF類型如何影響mutation與storage
25.5 批量mutation
每個mutation都可能包含多個RDF三元組漩蟆,對于大的數(shù)據(jù)上傳操作垒探,這些mutation可以批量、并發(fā)執(zhí)行怠李。工具dgraph-live-loader
就是用于干這個的圾叼,默認是每批1000行RDF,同時并發(fā)100個
Dgraphloader以一個gzip壓縮格式的N-Quad文件(不含{ set {
的三元組列表)捺癞,具體查看Bulk Data Loading
25.6 刪除
刪除操作夷蚊,是用delete
關(guān)鍵字標志的,它可以從存儲中移除三元組
例如髓介,如果存儲中含有:
<0xf11168064b01135b> <name> "Lewis Carrol"
<0xf11168064b01135b> <died> "1998"
那么刪除的mutation:
{
delete {
<0xf11168064b01135b> <died> "1998" .
}
}
刪除不需要的數(shù)據(jù)惕鼓,并將它從索引中移除(如果有索引的話)
對于刪除語句S P *
,會將節(jié)點N
所有謂語P
的數(shù)據(jù)(以及相關(guān)索引)都移除
{
delete {
<0xf11168064b01135b> <author.of> * .
}
}
對于語句S * *
,會刪除節(jié)點S
所有的出邊(但是唐础,節(jié)點自己可能會作為某些邊的終點留存下來)箱歧,另外被刪除的邊相關(guān)的任意反向邊矾飞,還有被刪除的數(shù)據(jù)的所有索引也都會被刪除
{
delete {
<0xf11168064b01135b> * * .
}
}
注意,
* P O
與* * O
是不被支持的呀邢,因為找到所有的入邊太難了