使用图
在图数据库中,数据库系统将数据画成一个类网状的结构,由顶点和边组成。在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可以保证一致性。更多特殊的命令,可以参考:
案例: 餐馆顾客的社交网络
当你选择在你的数据库中使用顶点和边时,扩展标准的V
和E
类来适配你的需求。这种方式的好处是:
- 对实体的含义可以更好的理解。
- 在类级别可以选择一些约束。
- 通过对实体分区,可以改进性能。
- 允许在图的元素上继承属性。
例如,基于餐馆的社交网络。需要单独的客户类和他们吃过的餐馆类。基于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
扩展自E
, Eat
表示顶点Person
和顶点Restaurant
之间的关系。
当你创建类的边时,顶点的指向很重要,因为它决定了关系的含义。例如,创建一个反向的边,从Restaurant
到Person
, 应该创建一个单独的类叫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:0
在in_
字段。
你可以访问所有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.