Dgraph-查詢語言

查詢語言

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的sincefacet應該按如下的方式查詢:

{
  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的別名

在查詢某個謂語時滥崩,可以指定別名夭委,格式類似于請求其他謂語的別名株灸。orderascorderdesc不能用作別名慌烧,因為它們有特別意義屹蚊,其他的任何字符串都能用作別名

在這里,我們給分別給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é)果時不同的

  1. depth=1活逆,查詢到genre
{
  "data": {
    "me": [
      {
        "uid": "0x1de841",
        "name@en": "Drama"
      }
    ]
  }
}
  1. 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"
          }
        ]
      }
    ]
  }
}
  1. 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"
              }
            ]
          }
        ]
      }
    ]
  }
}
  1. 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"
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  }
}
  1. 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, boolgeo

而string與dateTime類型有多個索引類型

24.5.1 string索引

string類型有如下索引類型:

Dgraph function Required index / tokenizer Notes
eq hash, exact, term, or fulltext 對于 eq 函數(shù)來說性能最好的索引類型是 hash. 只有相似需要eq的同時還需要全文檢索的時候诫隅,再考慮使用 termfulltext 索引腐魂。如果已經(jīng)在用term了,那就無需再用hashexact
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ù)以及排序

  • intfloat索引是可排序的
  • 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 是不被支持的呀邢,因為找到所有的入邊太難了

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末洒沦,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子驼鹅,更是在濱河造成了極大的恐慌微谓,老刑警劉巖森篷,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件输钩,死亡現(xiàn)場離奇詭異,居然都是意外死亡仲智,警方通過查閱死者的電腦和手機买乃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來钓辆,“玉大人剪验,你說我怎么就攤上這事∏傲” “怎么了功戚?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長似嗤。 經(jīng)常有香客問我啸臀,道長,這世上最難降的妖魔是什么烁落? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任乘粒,我火速辦了婚禮,結(jié)果婚禮上伤塌,老公的妹妹穿的比我還像新娘灯萍。我一直安慰自己,他們只是感情好每聪,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布旦棉。 她就那樣靜靜地躺著,像睡著了一般药薯。 火紅的嫁衣襯著肌膚如雪他爸。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天果善,我揣著相機與錄音诊笤,去河邊找鬼。 笑死巾陕,一個胖子當著我的面吹牛讨跟,可吹牛的內(nèi)容都是我干的纪他。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼晾匠,長吁一口氣:“原來是場噩夢啊……” “哼茶袒!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起凉馆,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤薪寓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后澜共,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體向叉,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年嗦董,在試婚紗的時候發(fā)現(xiàn)自己被綠了母谎。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡京革,死狀恐怖奇唤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情匹摇,我是刑警寧澤咬扇,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站廊勃,受9級特大地震影響懈贺,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜供搀,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一隅居、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧葛虐,春花似錦胎源、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至的诵,卻和暖如春万栅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背西疤。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工烦粒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓扰她,卻偏偏與公主長得像兽掰,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子徒役,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Take a Tour Dgraph的GraphQL+-是一種基于facebook的GraphQL的圖查詢語言孽尽。G...
    羽_da59閱讀 3,898評論 2 3
  • 關(guān)于Mongodb的全面總結(jié) MongoDB的內(nèi)部構(gòu)造《MongoDB The Definitive Guide》...
    中v中閱讀 31,938評論 2 89
  • 正文之前 本文有很多的參考來源,就不一一列舉了忧勿。除了少部分自己寫的杉女,其他的都是從別的地方拼湊來的。但求不噴鸳吸,不圖啥...
    張照博閱讀 36,467評論 3 31
  • 人是一種奇怪的生物熏挎,他具有其它物種所沒有的敏感情緒。別人的一舉手层释、一投足婆瓜,或是一句話快集、一個表情都也可能使我們原本平...
    迷迭香榭閱讀 587評論 0 0
  • 寫在前面 新文來啦贡羔!和之前的文區(qū)別會比較大,一直都想寫一個現(xiàn)實一點的東西个初,算是一次新的嘗試吧乖寒。大概是隨著年齡的增長...
    作者熄歌閱讀 484評論 0 5