使用图

在图数据库中,数据库系统将数据画成一个类网状的结构,由顶点和边组成。在OrientDB中图模型, 数据通过属性图的概念表示,一个顶点是一个实体连接其他顶点,一个边是一个实体连接两个顶点。

OrientDB自带了一个持久的顶点类叫V,边的叫E。例如,可以使用 INSERT命令利用V创建一个顶点。

orientdb> INSERT INTO V SET name='Jay'

Created record with RID #9:0

实际上,图模型数据库工作在文档模型之上。但是,为了简化过程,OrientDB引入了一套命令来管理图。可以使用CREATE VERTEX来替代INSERT

orientdb> CREATE VERTEX V SET name='Jay'

Created vertex with RID #9:1

通过在标准SQL语法上使用图的命令,OrientDB可以保证一致性。更多特殊的命令,可以参考:

案例: 餐馆顾客的社交网络

当你选择在你的数据库中使用顶点和边时,扩展标准的VE类来适配你的需求。这种方式的好处是:

  • 对实体的含义可以更好的理解。
  • 在类级别可以选择一些约束。
  • 通过对实体分区,可以改进性能。
  • 允许在图的元素上继承属性。

例如,基于餐馆的社交网络。需要单独的客户类和他们吃过的餐馆类。基于V类创建这些类。

orientdb> CREATE CLASS Person EXTENDS V

orientdb> CREATE CLASS Restaurant EXTENDS V

这就创建了社交网络的模式了,下面添加数据。

orientdb> CREATE VERTEX Person SET name='Luca'

Created record with RID #11:0


orientdb> CREATE VERTEX Person SET name='Bill'

Created record with RID #11:1


orientdb> CREATE VERTEX Person SET name='Jay'

Created record with RID #11:2


orientdb> CREATE VERTEX Restaurant SET name='Dante', type='Pizza'

Created record with RID #12:0


orientdb> CREATE VERTEX Restaurant SET name='Charlie', type='French'

Created record with RID #12:1

增加了三个Person类的顶点, 表示社交网络的3个人。增加两个Restaurant类的节点,表示他们能赞助的餐馆。

创建边

这是,顶点之间是独立的,之和自身的类绑定,还没有边关联。在建立连接之前,先创建基于E创建一个类。

orientdb> CREATE CLASS Eat EXTENDS E

Eat扩展自EEat表示顶点Person和顶点Restaurant之间的关系。

当你创建类的边时,顶点的指向很重要,因为它决定了关系的含义。例如,创建一个反向的边,从RestaurantPerson, 应该创建一个单独的类叫Attendee

用户Luca吃了Dante的匹萨。创建一个边,表示这个关系:

orientdb> CREATE EDGE Eat FROM ( SELECT FROM Person WHERE name='Luca' )
          TO ( SELECT FROM Restaurant WHERE name='Dante' )

从RID创建边

如果你知道顶点的RID,可以直接使用简短快速的命令直接连接它们。例如, Bill吃了Dante,Jay吃了Charlie。创建类Eat来表示:

orientdb> CREATE EDGE Eat FROM #11:1 TO #12:0

orientdb> CREATE EDGE Eat FROM #11:2 TO #12:1

查询图

上面的例子建立一个小型的客人和餐馆的社交网络。你可以开始尝试在图数据库上查询。

你可以使用特定的图函数来穿过边,例如:

  • OUT() 获取邻接的出度节点
  • IN() 获取邻接的入度节点
  • BOTH() 获取邻接的出度和入度节点

例如,找到所有吃过餐馆Dante的顾客, RID是#12:0, 你可以访问这个餐馆的记录,然后遍历入度的边来发现连接它的Person 类。

orientdb> SELECT IN() FROM Restaurant WHERE name='Dante'

----+------+----
#   |@CLASS|IN
----+------+----
0   |null  |[2]
----+------+----

这个查询显示连接餐馆Dante的Person类的RID。可以使用EXPAND()函数来看到顶点集合的结果信息。

orientdb> SELECT EXPAND( IN() ) FROM Restaurant WHERE name='Dante'

-------+-------------+-------------+---------+
 @RID  | @CLASS      | Name        | out_Eat |
-------+-------------+-------------+---------+
 #11:0 | Person      | Luca        | #12:0   |
 #11:1 | Person      | Bill        | #12:0   |
-------+-------------+-------------+---------+

创建边连接顾客

目前只展示了顾客和餐馆之间的关系。尽管很有趣,但是还不是一个社交网络。你需要建立边连接顾客。

先基于E创建新类:

orientdb> CREATE CLASS Friend EXTENDS E

用户Luca和Jay是朋友。RID分别是#11:0#11:2。创建一个边连接他们。

orientdb> CREATE EDGE Friend FROM #11:0 TO #11:2

Friend关系,方向不重要。关系是双向的,可以使用BOTH()函数来查询。

orientdb> SELECT EXPAND( BOTH( 'Friend' ) ) FROM Person WHERE name = 'Luca'

-------+-------------+-------------+---------+-----------+
 @RID  | @CLASS      | Name        | out_Eat | in_Friend |
-------+-------------+-------------+---------+-----------+
 #11:2 | Person      | Jay         | #12:1   | #11:0     |
-------+-------------+-------------+---------+-----------+

这里, BOTH()函数使用边的类Friend作为参数, 只寻找Friend类的关系, (也就是跳过Eat类)。在上述结果中,记录#11:0in_字段。

你可以访问所有Luca朋友吃过的餐馆。

orientdb> SELECT EXPAND( BOTH('Friend').out('Eat') ) FROM Person
          WHERE name='Luca'

-------+-------------+-------------+-------------+--------+
 @RID  | @CLASS      | Name        | Type        | in_Eat |
-------+-------------+-------------+-------------+--------+
 #12:1 | Restaurant  | Charlie     | French      | #11:2  |
-------+-------------+-------------+-------------+--------+

轻量级的边

1.4.x版本,OrientDB开始使用轻量级的边(默认不开启)。轻量级的边没有RID,但是会存储在顶点里。注意,OrientDB只有在边没有属性的时候会使用轻量级的边,否则就是一个普通的边。

从逻辑的观点看,轻量级的边就是边,所以任何图函数都可以使用。它可以提高性能,减少磁盘空间。

因为轻量级的边无法独立存在,一些查询估计跑不通。例如,

orientdb> SELECT FROM E

大多数情况,一个边会连接顶点,所以这个查询不会有问题。但是,它不会返回轻量级的边。如果你需要直接查询边,包括没有属性的,那就禁用轻量级边的特性,执行如下命令

orientdb> ALTER DATABASE CUSTOM useLightweightEdges=FALSE

这个命令你只需要执行一次,后续产生的新边都是标准的边,而不是轻量级的。注意,这不会影响已经存在的边。

更多关于轻量级边的故障排除,请见Why I can't see all the edges。更多OrientDB图模型的信息,参考图API.