[关闭]
@gzm1997 2018-10-10T10:18:13.000000Z 字数 3642 阅读 4274

dgraph图数据库

dgraph database


schema

dgraph的节点分为两类

  1. node节点
  2. value字面量

例如:

那么a b是两个节点 12是字面量 那么friend跟age都是谓语 friend指向b b是一个node age指向12 12是一个字面量 那么谓语所处的边为什么有时候指向一个node 有时候指向一个字面量呢 这就是由模式所定义的 或者说模式就是边的定义或者说模式就是谓语的定义

1.添加模式

当我们项添加数据到已有的模式中 我们可以直接添加 但是我们需要添加新数据到还没有存在模式中的时候 可以有两种方式

在模式中我们需要定义索引 因为dgraph的函数跟filter过滤器都是只可以应用于添加了索引的谓语 不在模式中添加索引的话 那么各种查询进行不了

image_1ci6k5u3ir3810kr17jd1641jud40.png-28.8kB

2.查询模式

  1. schema(pred: [name, age, friend, owns_pet]) {
  2. type
  3. index
  4. }

输出 很显然下面的输出都是按照谓语一个一个输出这个谓语指向的那个的类型(是node还是字面量) 以及是否具有索引 如果为false就不输出

  1. {
  2. "data": {
  3. "schema": [
  4. {
  5. "predicate": "age",
  6. "type": "int",
  7. "index": true
  8. },
  9. {
  10. "predicate": "friend",
  11. "type": "uid"
  12. },
  13. {
  14. "predicate": "name",
  15. "type": "string",
  16. "index": true
  17. },
  18. {
  19. "predicate": "owns_pet",
  20. "type": "uid"
  21. }
  22. ]
  23. },
  24. "extensions": {
  25. "server_latency": {
  26. "encoding_ns": 1000000
  27. },
  28. "txn": {
  29. "start_ts": 20,
  30. "lin_read": {}
  31. }
  32. }
  33. }

dgraph支持的数据类型


编码

dgraph是使用utf-8进行编码的 一些谓语也是使用字符串来存储的 可以在加上语言标签来定义是什么语言

节点加上语言标签进行声明

"Amit"@en

Amit这个名字是英文

多个语言匹配

@lang1:...:langN

上面这个语法的特点

使用语言pipei匹配来查询一个人的朋友他的朋友名字各种语言都有

  1. {
  2. language_support(func: allofterms(name@hi, "अमित")) {
  3. name@bn:hi:en
  4. age
  5. friend {
  6. name@ko:ru:.
  7. age
  8. }
  9. }
  10. }

输出

  1. {
  2. "data": {
  3. "language_support": [
  4. {
  5. "name@bn:hi:en": "অমিত",
  6. "age": 35,
  7. "friend": [
  8. {
  9. "name@ko:ru:.": "Michael",
  10. "age": 39
  11. },
  12. {
  13. "name@ko:ru:.": "상현",
  14. "age": 24
  15. },
  16. {
  17. "name@ko:ru:.": "Артём",
  18. "age": 35
  19. }
  20. ]
  21. }
  22. ]
  23. },
  24. "extensions": {
  25. "server_latency": {
  26. "encoding_ns": 1000000
  27. },
  28. "txn": {
  29. "start_ts": 58,
  30. "lin_read": {
  31. "ids": {
  32. "1": 6
  33. }
  34. }
  35. }
  36. }
  37. }

查询格式

其实上面的查询语句一直都是有规矩可循的 但是一直没有注意到

之前我们说到dgraph有两种节点

常见的两种形式
image_1ci68dk4oo2r1gn4c3qpga18d152.png-10.3kB

谓语不属于节点

在查询上

如下 查询Michael的字面量: name age (这些都是他指向的字面量) 以及他的朋友(他的朋友就是他指向的节点)

image_1ci6539gh1jp8kvq1aj9j5610hl9.png-29.5kB

所以我们要进一步查询Michael的朋友的宠物 只要在上面的查询语句稍加修改即可
微信图片_20180712103548.png-20.7kB


过滤器

常见过滤器

1.节点上的过滤器

allOfTerms(node_name, "term1 ... termN")

节点的名字含有给出的所有单词

anyOfTerms(node_name, "term1 ... termN")

节点的名字函数给出的单词列表中的任意一个单词

2.边上的过滤器
边上的过滤器可以应用到int float string date类型的边上

image_1ci698cfo30h1pi9cot8uh15ut5f.png-25.5kB

过滤器上可以使用逻辑AND OR NOT将过滤条件联合起来

  1. {
  2. michael_friends_and(func: allofterms(name, "Michael")) {
  3. name
  4. age
  5. friend @filter(ge(age, 27) AND le(age, 48)) {
  6. name@.
  7. age
  8. }
  9. }
  10. }

排序

可以使用下面两个关键字进行排序

注意 排序只是在返回的json对象上有效果 在UI的可视化上是没效果的

image_1ci69hu24163uvv11q8f1a0eih15s.png-22.3kB


分页

image_1ci6a1bp71l331f50jcsd7d189f79.png-20kB


count

dgraph的count用起来挺方便
image_1ci6a8vhm1gcv1bf0sfikeh1csk7m.png-13.8kB


根节点

因为有时候dgraph的图非常大 那么从所有节点开始搜索是很低效的 那么根节点的概念就出现了 从根节点开始搜索

在根节点处 我们是使用func:和一个函数来找到一个初始化的节点集合

但是root节点的那个函数func是不可以接受and or not那些逻辑操作的 所以如果需要在根节点处加上这些逻辑操作需要在后面自己加一个filter过滤器

image_1ci6e87bj1dr3lmjcotgm7aci83.png-18.9kB


根据谓语(边)查询

image_1ci6hoimm59ufol1nmu125u1snj8g.png-17.2kB


alias别名

别名可以用于设置返回的json对象中key的名字 改成自己想要设置成的别名
image_1ci6hs52rbcl10hj1s3kbd95m58t.png-20kB


级联cascade指令

级联的概念开始真的是有点难以理解 举个例子就容易多了

image_1ci6iv71ofb6jfdmlp1rasfjt9.png-15.1kB
上面的查询是查询Michael年纪大于等于70的朋友 Michael有年纪大于等于70的朋友就直接返回在friend的列表里 如果没有那么friend一项就直接为空

但是加上@cascade之后效果就不一样了
image_1ci6j4lgv16r38pugr4ll91isl1m.png-51.3kB

上面加上了@cascade之后 如果Michael如果有年纪大于鞥与70的朋友那么Michael跟她的朋友一起在返回的结果里面 但是如果没有 那么连Michael也不返回

因为级联就相当于强行的逻辑与如果后面的节点不满足要求 那么前面已经满足匹配的节点也不会被返回


normal指令

@normalize指令

image_1ci6jhmbl1ptpu9k130n1ot71q5p33.png-52.2kB


数据突变

数据突变就是修改存储在Dgraph中的图结构
image_1ci6knlvgq8l1tnb1fif1qiddev5d.png-81.9kB


External Identifiers外部标识符

Dgraph是不支持为node设置外部标记符的 所以如果开发人员希望为节点添加一个外部标记符 那么需要自己添加一条边作为外部标记符


语言支持

这个语言标记上面已经减了很多次了 其中中文的标志使用以下来标志

_:myID <an_edge> "某物"@zh-Hans .

反向边

边是有向的一个查询是不可以反向遍历的 有两种方式可以双向进行查询


整合已有数据

当我们第一批次向数据库中导入了一系列的人物关系数据 第二批次的时候导入了一系列的公司数据 那么问题在于我们怎么把这些人物和公司关联起来呢?

答案肯定是添加新的模式 但是添加新的模式要注意 因为我们肯定不能在新的模式中使用下面

_:sarah <works_for> _:company1 .

因为这样的话会为z这个sarah新建一个uid 而不是我们之前的那个sarah 这是一个新的sarah 正确的做法应该是

<uid-for-sarah> <works_for> <uid-for-company1> .

找到sarah和company的uid根据uid定义这些已存在节点之间的新模式

例子

  1. {
  2. set {
  3. <0x2> <boss_of> <0xd> .
  4. }
  5. }

删除数据

删除数据有三种

方式

image_1ci6mejsl1l8t33ophi167a1j585q.png-12.4kB


谓语查询

可以根据一个node节点查询这个节点所有的谓语
使用

_predicate_

image_1ci6migc0iel3o5v010j114hv67.png-52.3kB


拓展谓语

expand(_all_)

上面是查询所有的谓语 拓展谓语是根据给定的谓语进行深入查询 而不是单纯在返回结果中列出他们

image_1ci6mt3qg17abbh479c17cp1n1i74.png-40.4kB


多个查询块

没什么区别 就是多几个查询根节点而已
image_1ci6p35ni1idvl5j13ja12q7qdg7h.png-26.7kB


查询变量

结果可以被存在变量里面 可以在查询的任意一个位置被使用

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注