当前位置: 首页 > 工具软件 > Dgraph > 使用案例 >

Dgraph使用总结

马坚白
2023-12-01

Dgraph使用总结

纲要

  • 1.背景
  • 2.概念
  •   2.1 Schema
  •   2.2 数据写入
  • 3.查询
  •   3.1 Function/Filter
  •   3.2 查询变量
  •   3.3 Facets
  •   3.4 Recurse Query
  •   3.5 K-Shortest Path Queries
  • 4.部署
  •   4.1 单机部署
  •   4.2 集群部署

1.背景

  Dgraph是一个分布式的开源图数据库, 官方文档地址https://docs.dgraph.io/, 建议英文水平好的朋友可以直接去访问了解. 本文仅是对自己使用Dgraph的过程做一个总结, 着重介绍它的查询语法和一些有用而有重要的查询.

2.概念

2.1 Schema

  Dgraph和其它的大多数数据库一样, 也用schema来描述数据的类型(本质上都是图的边), 支持的类型如下

类型描述
int64位有符号整数
float双精度浮点数
string字符串
bool布尔类型
dateTimeRFC3339格式时间戳
geo地理位置类型
passwordstring (encrypted)
uid图的边类型,用于由一个节点指向另一个节点,且带有方向

Dgraph中有节点和值两种类型, 每个节点都有一个内部分配的64位整数的uid属性, 用于唯一标记该节点. 节点与节点之间由 uid类型的边连接, 节点与值之间由标量类型的边连接.

2.2 数据写入

  Dgraph的数据导入遵循W3C标准RDF格式, 这个格式是一种三元组格式, 形式如下:

<subject> <predicate> <object> .

subject 代表图的一个节点, predicate代表节点的边名, object代表边的值(值的类型就是上述schema的类型)

  写入例子1:

<0x01> <name> "Alice" .

  这个三元组, 在图的场景下表示相当于: uid=0x01的节点的name边指向了字符串Alice, 在关系数据库的场景相当于: 更新id=1的记录的name字段为Alice

  写入例子2:

_:alice <name> "Alice" .
_:alice <friend> _:bob .
_:bob <name> "Betty" .

  在不知道uid的场景下, 写入数据时每个节点由dgraph内部分配一个uid, 且可以用_:identifier的形式代表该节点, 以方便后面继续使用. 比如上述例子表示, 名叫"Alice"的人(即节点)有个名叫"Betty"的朋友.


  除了三元组的格式外, dgraph还提供了json格式的数据写入, 比如 写入例子2 的三元组可用下面json表示:

{
  "uid": "_:alice",
  "name": "Alice",
  "friend": {
    "uid": "_:bob",
    "name": "Betty"
  }
}

3. 查询

  Dgraph的查询语法是以GraphQL为基础, 在此基础上针对自身的需要会对该语法规则有所改变.

3.1 Function/Filter

  Dgraph使用functionfilter对查询数据进行过滤. 在dgraph中function和filter的区别仅在于放位置的不同.下面是支持的function和filter:

名称有效类型描述
alloftermsstring类似与like过滤, 如allofterms(predicate, "space-separated term list")表示过滤某个边的值必须同是包含space-separated,term和list三个词, 但忽略顺序.
anyoftermsstringallofterms类似, 但anyofterms只要求包含任一个词.
alloftextstring全文检索
regexpstring正则匹配, 语法为regexp(name, /^Steven*/)
eq,lt,le,gt,geint, float, string, dateTime分别代表=, <, <=, >, >=
uid/语法为uid(0x11,0x12), 根据传进来的uid值, 过滤相应节点
has/语法为has(name), 过滤有某条边的节点
and,or,not/逻辑过滤器, 用于联结上述的function/filter

  查询例子1:

{
  #查询名字里同时包含Farhan Akhtar的人
  q(func: allofterms(name, "Farhan Akhtar")) {
    uid
    name
  }
}

  查询例子2:

{
   #查询名字里以Steven开头的导演和他导演的含有ryan字符串的电影
  directors(func: regexp(name, /^Steven*$/)) {
    name
    director.film @filter(regexp(name, /ryan/i)) {
      name
    }
  }
}

3.2 查询变量

  dgraph可以通过as关键词将一个查询块的任意部分设为一个变量, 以供后面的子查询或者其它查询块使用. 这个变量本质上是一个uid列表, 因此要利用uid函数进行引用.

  通用的查询格式为:

{
  A as not_a_real_query(...) {
    B as some_edge @filter(...) { # can't use C or B in this filter
      C as ... { 
        # A, B and C here
      }

      # A, B and C here
    }

    # A, B and C can be used in any blocks here
  }

  # A, B and C can be used in any other query block
}

  查询例子1:

{
  #查询名叫"Peter Jackson"的人的自导自演电影和扮演的角色
  PJ as var(func:allofterms(name, "Peter Jackson")) {
    F as director.film
  }

  peterJ(func: uid(PJ))  {
    name 
    actor.film {
      performance.film @filter(uid(F)) {
        film_name: name
      }
      performance.character {
        character: name
      }
    }
  }
}

3.3 Facets

  Dgraph 用facets描述边的自定义属性. 如两个用户间有一条叫friend的边, 可以利用facets在这friend边上设置一个close属性值表示他们的亲密度.

  带facets的数据写入例子:

_:alice <name> "Alice" .
_:alice <mobile> "040123456" (since=2006-01-02T15:04:05) .
_:alice <car> "MA0123" (since=2006-02-02T13:01:09, first=true) .

facets数据写入在最后的()里设置

  查询facets数据:

query
{
  data(func: eq(name, "Alice")) {
     name
     mobile @facets(since)
     car @facets(since)
  }
}

result
{
  "data": {
    "data": [
      {
        "name": "Alice",
        "mobile|since": "2006-01-02T15:04:05Z",
        "mobile": "40123456",
        "car|since": "2006-02-02T13:01:09Z",
        "car": "MA0123"
      }
    ]
  }
}

facets数据默认用predicate_name|facet_name的格式展示

3.4 Recurse Query

  Recurse Query也叫递归查询. 此查询会一层层的展开一组边,直到我们到达所有叶节点或达到的最大深度参数depth指定的深度.

  查询例子:

query
{	
    #查询member_id=60002581用户的2级下线
    event(func: allofterms(member_id, "60002581")) @recurse(loop: false, depth:3) {  
        member_id
        ~member_next_level_of 

	}
}

result
{
  "data": {
    "event": [
      {
        "member_id": "60002581",
        "~member_next_level_of": [
          {
            "member_id": "70005199",
            "uid": "0x459b"
          }
        ],
        "uid": "0x2382"
      }
    ]
  }
}

3.5 K-Shortest Path Queries

  也即最短路径查询, 用于查询Dgraph中两个节点的最短路径. 常见的使用场景为想要分析某用户与某产品之间的关系路径.
  查询例子:

query
{
      path as shortest(from: 0x24a, to: 0x4) {
        ~purchase
        purchase
      }
      
      path(func: uid(path)) {
	    uid
      }
}
result
{
  "data": {
    "path": [
      {
        "uid": "0x24a"
      },
      {
        "uid": "0x85"
      },
      {
        "uid": "0x1ca6"
      },
      {
        "uid": "0x4"
      }
    ],
    "_path_": [
      {
        "purchase": [
          {
            "~purchase": [
              {
                "purchase": [
                  {
                    "uid": "0x4"
                  }
                ],
                "uid": "0x1ca6"
              }
            ],
            "uid": "0x85"
          }
        ],
        "uid": "0x24a"
      }
    ]
  }
}

4.部署

  Dgraph支持单机部署和集群部署两种方式. 在Dgraph中有zero, alpha,ratel三类服务(也叫节点), 其中zero服务充当协调alpha的角色; alpha则是对外提供数据写入和查询的服务, 外部的客户端主要都是和alpha交互; ratel则是一个提供UI界面的服务, 方便用户写入/查询数据,查看/修改schema.

4.1 单机部署

  • 下载和安装
curl https://get.dgraph.io -sSf | bash   //这条指令会自动下载最新版本的dgraph并自动安装
  • 启动服务
//启动zero服务, 默认使用5080端口与外部通讯
dgraph zero    
//启动alpha服务, 默认使用9080端口与外部通讯
dgraph alpha --lru_mb 2048 --zero localhost:5080  
//启动ratel,  默认使用8000端口对外提供访问
dgraph-ratel     

4.2 集群部署

  假设集群机器数为3台

  • 下载和安装
    此步骤与单机部署的下载安装相同, 在3台机器上均执行上述指令.

  • 启动服务

//选择某一台机器上启动zero服务, 用my参数指定自身的host, 以便和集群的alpha服务通讯, 用replicas指定副本数
dgraph zero  --my dev210.sugo.net:5080 --replicas 3  
//在三台机器上启动alpha服务,  用my参数指定自身的host 
dgraph alpha --lru_mb 2048 --my dev210.sugo.net:7080 --zero dev210.sugo.net:5080   //210机器执行
dgraph alpha --lru_mb 2048 --my dev211.sugo.net:7080 --zero dev210.sugo.net:5080   //211机器执行
dgraph alpha --lru_mb 2048 --my dev212.sugo.net:7080 --zero dev210.sugo.net:5080   //212机器执行
//选择某一台机器启动ratel服务
dgraph-ratel     

注意:
集群模式下, 若zero设置了replicas参数, 则集群必须有半数以上的alpha节点存活才可对外提供服务. 在本例下, 即需要2个及以上数量的alpha节点存活才能提供服务.

 类似资料: