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 过滤
{
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 分页查询
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的容器)