几页前我们已经遇到过Graph Model。现在我们拥有了使用OrientDB作为GraphDB所需的所有基础知识!这需要OrientDB的图形版本。连接到GratefulDeadConcerts
数据库进行实验。它包含由“ Grateful Dead ”乐队演奏的音乐会。
OrientDB附带了一个名为“V”的通用Vertex持久类(以前版本中的OGraphVertex)和Edge中的“E”(过去的OGraphEdge)。您可以使用以下命令创建新的顶点:
orientdb> insert into V set name = 'Jay'
create record with RID #9:0
实际上,GraphDB模型在底层Document模型之上工作,因此到目前为止您学到的所有内容(记录,关系等)仍然有效。但是为了简化图形的管理,我们创建了特殊命令,因此不要再使用SQL Insert命令来创建新的顶点。相反,使用ad-hoc“create vertex”命令:
orientdb> create vertex V set name = 'Jay'
create vertex with RID #9:1
通过使用图形命令,OrientDB负责确保图形始终保持一致。所有Graph命令都是:
即使您可以使用顶点和边缘,OrientDB也可以扩展V
和E
类。这种方法的优点是:
所以从现在开始,我们将避免使用plain V
,E
并且将始终创建自定义类。让我们开发一个示例图来模拟基于餐馆的社交网络:
orientdb> create class Person extends V
orientdb> create class Restaurant extends V
现在已经创建了模式,让我们用一些顶点填充图形:
orientdb> create vertex Person set name = 'Luca'
create record with RID #11:0
orientdb> create vertex Person set name = 'Bill'
create record with RID #11:1
orientdb> create vertex Person set name = 'Jay'
create record with RID #11:2
orientdb> create vertex Restaurant set name = 'Dante', type = 'Pizza'
create record with RID #12:0
orientdb> create vertex Restaurant set name = 'Charlie', type = 'French'
create record with RID #12:1
在我们使用边连接它们之前,让我们创建一个新的Edge类型:
orientdb> create class Eat extends E
这将代表人与餐馆之间的关系。创建边时,方向很重要,因为它给出了关系的含义。如果我们想要以相反的方向对边缘进行建模,从餐厅到人,我们可能会将边缘类称为“参加者”或类似的东西。
现在让我们在“Luca”和“Dante”餐厅之间建立联系:
orientdb> create edge Eat from (select from Person where name = 'Luca') to (select from Restaurant where name = 'Dante')
如果您知道顶点的RID,则可以使用更短更快的命令连接它们。下面我们将“Bill”与同一个“Dante”餐厅和'Jay'连接到'Charlie'餐厅:
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),我们可以获取Dante的记录,然后遍历传入的边缘以发现连接的人物记录:
orientdb> select in() from Restaurant where name = 'Dante'
+-------+----------------+
| @RID | in |
+-------+----------------+
| #-2:1 | [#11:0, #11:1] |
+-------+----------------+
这些是连接的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 |
+-------+-------------+-------------+---------+
好多了!现在让我们创建新的关系“朋友”来联系人:
orientdb> create class Friend extends E
并将“Luca”与“Jay”联系起来:
orientdb> create edge Friend from #11:0 to #11:2
“朋友”关系是这些边缘类型中的一种,其中方向并不重要:如果“Luca”是“Jay”的朋友,则相反通常是正确的,因此方向失去重要性。要发现Luca的朋友,我们应该使用这个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 |
+-------+-------------+-------------+---------+-----------+
在这种情况下,我已经通过Edge的类“朋友”作为函数的参数,both()
以便只交换善良的“朋友”的关系(所以这次跳过“吃”)。另请注意,结果集中与“Luca”(RID =#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 |
+-------+-------------+-------------+-------------+---------+
很酷,不是吗?
默认情况下,从OrientDB v1.4.x边缘开始,它们作为轻量边缘进行管理:它们没有自己的标识作为记录,但在物理上存储为顶点内的链接。仅当边没有属性时,OrientDB才会自动使用Lightweight边,否则使用常规边。从逻辑的角度来看,轻量级边缘是所有效果的边缘,因此所有图形函数都能正常工作。这是为了提高性能并减少磁盘空间。但结果是,由于轻量级边缘不作为数据库中的单独记录存在,因此以下查询不会返回轻量级边缘:
SELECT FROM E
在大多数情况下,边缘使用边缘,因此这不会导致任何特定问题。如果您需要直接查询Edges,即使没有属性,也可以通过执行以下命令禁用轻量级边缘功能:
ALTER DATABASE CUSTOM useLightweightEdges=false
这仅对新边生效。有关更多信息,请访问:https://github.com/orientechnologies/orientdb/wiki/Troubleshooting#why-i-cant-see-all-the-edges。
有关更多信息,请参阅Graph API。