dgraph学习(二)

  • dgraph简介
  • dgraph组件
  • dgraph数据类型
  • 支持数据类型
  • 索引及分词器
  • dgraph操作
  • alter
  • mutate
  • Blank UID(不推荐,系统会把输入错误的节点当作空节点)
  • Explicit UID
  • 操作
  • 新增:
  • 修改:
  • 删除:
  • upsert
  • query
  • 根节点
  • 扩展查询
  • filter 过滤
  • Sorting (orderasc or orderdesc)
  • pagination 分页查询
  • count 算一个人的朋友数
  • filter 进一步筛选
  • Has
  • Alias别名
  • @cascade(级联) 删除未匹配字段
  • @normalize 返回别名
  • Comments
  • 语言支持
  • 反向边 Reverse edges
  • 删除操作
  • 清除所有数据


dgraph简介

dgraph组件

  • ratel:提供用户界面来执行数据查询,数据修改及元数据管理。
  • alpha:用于管理数据(谓词和索引),外部用户主要都是和 alpha 进行数据交互。
  • group:多个 alpha 组成一个 group(即图中同色 alpha),group 中的多个 alpha 通过 raft协议保证数据一致性。
  • zero:用于管理集群,并在 group 之间按照指定频率去均衡数据。

dgraph数据类型

支持数据类型

数据类型

说明

defalut

默认类型

int

64 位有符号整数

float

64 位双精度浮点数

bool

布尔

geo

地理位置,目前支持 Point、Polygon、MultiPolygon

datetime

时间类型,如 2020-12-02

string

字符串

password

密码

uid

边的类型,64 位整形,以 16 进制形式表示,如 0x1,系统默认分配

索引及分词器

Dgraph 基于每种数据类型,提供了不同的索引及其分词器。目前,建立索引及分词器的意义在于,建立以后可以使用相应的系统函数。

数据类型

可用索引

index 索引可用的 tokenizer(索引类型)

defalut

list count index upsert

defalut

int

同上

int

float

同上

float

bool

同上

bool

geo

同上

geo

datetime

同上

year month day hour

string

list count lang index upsert

exact hash term fulltext trigram

password

-

-

uid

list count reverse

-

注:

  • count 需要和 list 配合使用,即选用 list 后,才可选用 count
  • upsert 需要和 index 配合使用,即选用 index 后,才可选用 upsert
  • 对于 string 类型使用 tokenizer 时,exact、hash、term 只能任选其一

dgraph操作

当前,Dgraph 提供 ratel、http、client 三种方式对图数据库进行相应操作。接下来将通过 ratel 的方式来介绍 Dgraph 的常规操作。

alter

说明: 操作图数据库元数据,如 schema、type 的新增、修改、删除等。
格式:

< 谓词 >: 类型 索引类型 .

示例:

<test_age>: int @index(int) .
<test_name>: string @index(term) .
<test_friend>: [uid] .

当然也可以根据ui界面操作,点击Schema >> Add Predicate/Types

mutate

说明:在dgraph中对数据的增加修改都称为mutation,对图数据进行相应的新增、修改、删除等。
In Dgraph the mutation operations consist of two patterns: blank UID reference or explicit UID reference.

Blank UID(不推荐,系统会把输入错误的节点当作空节点)

underline + a colon + unique name (identifier)

json

{
  "uid": "_:diggy",
  "name": "diggy",
  "dgraph.type": "Food",
  "food": "pizza"
}

Explicit UID

json

{
  "uid": "0x4e030f",
  "somePredicate": "some new data"
}

操作

新增:
{
    set{
	    _:任意标识符 < 谓词 > "值" . 
    }
}

示例:

新增两条数据,jack 及 rose,他们为朋友关系

{
    set{
      _:jack <test_name> "jack" .
      _:jack <test_age> "20" . 
      _:jack <test_friend> _:rose .
      _:rose <test_name> "rose" .
      _:rose <test_age> "22" .
    }
}
修改:
{
    set{
	    <uid> < 谓词 > "新值" . 
    }
}
删除:

删除节点,如果定义了节点的<dgraph.type>,可以使用如下代码删除节点

There are three deletion options inside a delete mutation.

<uid> <edge> <uid>/"value" . Delete a single triple
<uid> <edge> * . Delete all triples for a given edge
<uid> * * . Delete all triples for a given node
# TODO: Change this to the new TYPE System.
{
  delete {
    # Delete a single triple.
    <0x1c3eb> <name> "Steven" .
    <0x1c3eb> <age> "38" .
    # Note: You need to know the value/Object to use "S P O". Otherwise use "S P *".

    # Delete an edge for a given node "S P O".
    <0x1c3eb> <friend> <1x1c2a1> .

    # Delete all triples for a given edge "S P *".
    <0x1c3eb> <friend> * .

    # Delete all triples for a given node "S * *".
    <0x1c3eb> * * .
  }
}
{
    delete{
	    <uid> < 谓词 > * . 
    }
}

upsert

说明: 对符合条件的数据进行新增或修改,类似 query+mutate 的组合。

格式:

upsert{
  query{
    自定义方法名(func:方法){
      v as uid //将 uid 赋值给变量 v
    }
  }
  
  mutation{
    set{
      uid(v) < 谓词 > "值" .
    }
  }
}

示例:
通过 upsert 将 jack 的 test_age 改为 31

upsert{
  query{
    find(func:eq(test_name, "jack")){
      v as uid
    }
  }
  
  mutation{
    set{
      uid(v) <test_age> "31" .
    }
  }
}

query

说明: 查询图数据库信息,如数据,schema 结构等。

格式:

{
  自定义方法名(func:方法){
    结果中需要展示的谓词
  }
}

根节点

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

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

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

扩展查询

可以嵌套使用

{
  expand(func: allofterms(name, "Ivy")) {
    expand(_all_) {
      expand(_all_) {
        expand(_all_)
      }
    }
  }
}

事例,查询朋友以及所有的扩展朋友

{
  everyone(func: anyofterms(name, "Michael Catalina")) {
    name
    friend {
      name
      friend { expand(_all_) { expand(_all_) } }
    }
  }
}

查询一个人的信息

{
  find_someone(func: eq(name, "...name in here...")) {
    name
    age
  }
}
{
  find_someone(func: uid(...uid number here...)) {
    name
    age
  }
}
schema(pred: [name, age, friend, owns_pet]) {
  type
  index
}

查询一个人的朋友,以及他的宠物

{
  michael_friends_and_pet(func: eq(name@., "Michael")) {
    name
    age
    friend {
      name@.
    }
    owns_pet {
      name
    }
  }
}

查询一个人的朋友的朋友

{
  michael_friends_friends(func: allofterms(name@., "Michael")) {
    name
    age
    friend {
      name@.
      friend {
        name@.
      }
    }
  }
}

filter 过滤

java连接禅道_数据类型

{
  michaels_friends_filter(func: allofterms(name@., "Michael")) {
    name
    age
    friend @filter(ge(age, 27)) {
      name@.
      age
    }
  }
}
{
  michael_friends_and(func: allofterms(name@., "Michael")) {
    name
    age
    friend @filter(ge(age, 27) AND le(age, 48)) {
      name@.
      age
    }
  }
}

Sorting (orderasc or orderdesc)

orderasc 从小到大排序
orderdesc 从大到小排序
注意 排序只是在返回的json对象上有效果 在UI的可视化上是没效果的

{
  michael_friends_sorted(func: allofterms(name@., "Michael")) {
    name
    age
    friend (orderasc: age) {
      name@.
      age
    }
  }
}

pagination 分页查询

java连接禅道_数据类型_02


first: N 只返回前N个结果

offset: N 跳过前N个结果

after: uid 返回在这个uid后面的结果

{
  michael_friends_first(func: allofterms(name@., "Michael")) {
    name
    age
    friend (orderasc: name@., offset: 1, first: 2) {
      name@.
    }
  }
}

count 算一个人的朋友数

{
  michael_number_friends(func: allofterms(name@., "Michael")) {
    name
    age
    count(friend)
  }
}

filter 进一步筛选

query_name(func: foo(…)) @filter(… AND …) {…}

{
  lots_of_friends(func: ge(count(friend), 2)) @filter(ge(age, 20) AND lt(age, 30)) {
    name@.
    age
    friend {
        name@.
    }
  }
}

Has

has(edge_name)

{
  have_friends(func: has(friend)) {
    name@.
    age
    number_of_friends : count(friend)
  }
}

返回三个字段,name,age,number_of_friends

Alias别名

{
  michael_number_friends(func: allofterms(name@., "Michael")) {
    persons_name : name
    age
    number_of_friends : count(friend)
  }
}

@cascade(级联) 删除未匹配字段

1、指令删除查询中没有所有匹配边的节点。
2、另一个用途是删除块中的筛选器没有返回结果的节点。

返回Michael所有朋友,无论有没有pet

{
  michael_friends_with_pets(func: allofterms(name@., "Michael")) {
    name
    age
    friend {
      name@.
      owns_pet
    }
  }
}

返回Michael所有朋友,没有pet的去掉,如果都没有pet那么Michael也不会返回

{
  michael_friends_with_pets(func: allofterms(name@., "Michael")) @cascade {
    name
    age
    friend {
      name@.
      owns_pet
    }
  }
}

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

@normalize 返回别名

只返回带有别名的节点
把结果扁平化 去除嵌套

{
  michael_and_pet_name(func: allofterms(name@., "Michael")) @normalize {
    name : name
    age
    owns_pet {
      pet: name
    }
  }
}
返回
"data": {
    "michael_and_pet_name": [
      {
        "name": "Michael",
        "pet": "Rammy the sheep"
      }
    ]
  },

Comments

注释#号开头

语言支持

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

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

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

多个语言匹配

@lang1:...:langN

上面这个语法的特点

最多只有一个结果返回,如果有结果出现在这个语言列表中 那么最左边那部分的匹配结果都会被返回,如果没有结果匹配就没有返回,但是如果最后时以 . 为结尾的话例外 .以为着什么语言都行 匹配上了就可以返回。

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

{
  language_support(func: allofterms(name@hi, "अमित")) {
    name@bn:hi:en
    age
    friend {
      name@ko:ru:.
      age
    }
  }
}

反向边 Reverse edges

设置为双向边 /alter

boss_of: [uid] @reverse .
works_for: [uid] @reverse .

查找在为CompanyABC工作的人

{
  q(func: eq(name, "CompanyABC")) {
    name
    work_here : ~works_for {
        uid
        name
    }
  }
}

删除操作

清除所有数据

1.用docker stop 关闭name 包含ratel和server的容器
2.进入name中包含zero的容器里(docker exec -it <容器id> /bin/bash)
3.进入后会自动进入/dgraph文件夹下,文件夹内包含p、w、zw以及其他文件或文件夹,删除P和W两个文件夹。
4、退出容器(ctrl+d),并使用docker stop 关闭此容器(name中包含zero的容器)
5、使用docker start 启动dgraph的三个容器(name 包含ratel、server、zero的容器)