基础概念
记录
你读取和存储的最小单元。记录有四种类型:
- 文档
- 字节流
- 顶点
- 边
一个 记录是你读取和存储在数据库中的最小单元。一个记录可以是一个文档,一个字节流(BLOB二进制大对象),一个顶点或者一条边。
文档
文档是OrientDB中最灵活的记录类型。文档默认有类型,通过约束的模式来定义,但是也可以使用无模式的。
文档以一种灵活的方式处理字段。你可以很方便的以json的格式导入导出。例如:
{
"name" : "Jay",
"surname" : "Miner",
"job" : "Developer",
"creations" : [
{
"name" : "Amiga 1000",
"company" : "Commodore Inc."
}, {
"name" : "Amiga 500",
"company" : "Commodore Inc."
}
]
}
对于文档,OrientDB支持复杂的 关系. 从开发这的角度来看,就是持久化的Map<String,Object>
。
字节流
除了文档记录类型,OrientDB可以加载和存储二进制数据。字节流记录类型类似于关系数据库中的BLOB
。
顶点
图数据库中,最基本的数据单元就是节点,OrientDB中叫做顶点。顶点为数据库存储信息。还有一个单独的记录类型叫做边,来连接顶点。
顶点也是文档。这意味着可以包含嵌入式的记录和任意类型。
边
在图数据库中,一个弧就是两个节点的连接,OrientDB叫做边(Edge)。 边是双向的,仅仅连接两个顶点。
边可以是常规的或者轻量级的。常规的边作为文档存储,而轻量级的边则不是。理解两者的区别,可以看轻量级边。
更多连接两个顶点的信息,可以参考接下来的关系。
记录ID
当OrientDB产生一条记录时,会自动分配一个唯一的单元标示,叫做Record ID,簇标示和位置组成的。格式如下:
#<cluster>:<position>
.
簇标示: 这个数字表示记录所属的簇。正数表示记录是被持久化的,负数表示临时存储,出现在使用投射(projections)的查询的结果中。
位置: 这个数字表示了在簇中的记录的绝对位置。
注意: 前缀符号
#
是标示记录ID的,强制性的。
记录不会失去它们的标示,除非被删除。删除的时候,OrientDB不会回收标示,除了local
存储。另外,你可以通过记录ID直接访问记录。因此,你不需要像关系数据库那样专门用一个字段存储主键。
记录版本
记录维护它们的版本号,每次更新都会增加。在使用乐观锁的事务中,OrientDB校验版本从而避免提交的时候产生冲突。
类
类的概念来自于面向对象编程体系。在OrientDB中,类定义记录。这非常接近于关系数据库中的表。
类可以是无模式,全模式或者混合的。它们可以继承自其它类,构成一个类的树型体系。 继承, 这种场景下,子类继承父类,继承了所有的属性。
每个类有自己的簇。一个类至少在一个簇下面,作为它的默认簇。但是,一个类可以支持多个簇。当你针对一个类执行查询时,自动传播到这个类的所有簇去查询。当你创建一个新的记录,OrientDB会使用配置的策略选择簇去存储这条记录。
当你创建一个新类时,默认,OrientDB会创建一个新的 持久化簇,和类的名称一样,小写的。
抽象类
抽象类的概念非常类似于面向对象编程中的概念。在OrientDB中,这个特征从1.2.0以后支持。抽象类作为定义其他类的基础。他们不能创建实例。更多信息参考创建类.
这个概念对于面向对象非常重要,避免了创建大量空的,自动创建的簇。
查询中的类和簇
类和簇的组合非常强大,有许多应用场景。当你创建一个类Invoice
,有两个簇invoice2015
and invoice2016
。你可以使用SELECT
查询这个类下所有记录。
orientdb> SELECT FROM Invoice
除此之外,你可以按照年来过滤结果集。类Invoice
包含一个year
属性, 你可以通过WHERE
语句过滤。
orientdb> SELECT FROM Invoice WHERE year = 2012
你可以指定单个簇中查询特定对象。通过将Invoice
分割到多个簇(例如按照年), 你可以通过缩小查询范围来优化查询。
orientdb> SELECT FROM CLUSTER:invoice2012
基于这个优化,查询会大大加速,因为OrientDB缩小了查询的目标簇。
关系
OrientDB支持两种类型的关系: 引用(referenced) and 嵌入(embedded)。可以以无模式或者全模式的方式管理关系。
引用的关系
在关系数据库中,表通过JOIN
关联查询,这样特别消耗计算资源。 OrientDB没有使用JOIN
来计算关系,而是直接存储到目标对象的链接。这加速了整个图(连接的对象形成的)的加载速度,例如在一个图和对象系统中。
例如
customer
Record A -------------> Record B
CLASS=Invoice CLASS=Customer
RID=5:23 RID=10:2
这里, 记录A
在属性customer
中包含了记录B
的引用。 记录相互可以被对方访问,因为有记录ID.
文档API中, 边被表示为两个链接,分别存储在对应的顶点中来处理双向连接关系。
1:1和1:n引用关系
OrientDB使用LINK
类型表示这个关系。
1:n和n:n引用关系
OrientDB使用链接集合来表示这些类型的关系:
LINKLIST
有序的链接列表。LINKSET
无序的链接集合,保证唯一性。LINKMAP
有序的链接映射表,String
作为键的类型。重复的键不能接受。
图API中, 边只能连接两个顶点。这意味着不支持1:n。用图来表示1:n关系,创建多个边jiu'xing'l。
嵌入关系
当使用嵌入关系时,OrientDB将对应记录嵌入进来。这些关系比引用关系更强大。你可以使用 UML Composition relationship来表示。
嵌入式的记录没有自己的记录ID, 所以你无法通过其他记录直接访问。但是可以通过容器记录(嵌入它的记录)访问。
这种情况下,你删除容器记录,嵌入的记录也会被删除。例如,
address
Record A <>----------> Record B
CLASS=Account CLASS=Address
RID=5:23 NO RID!
这里,记录A
包含整个记录B
在属性address
中。你通过遍历容器记录来找到B
。例如,
orientdb> SELECT FROM Account WHERE address.city = 'Rome'
1:1和n:1嵌入关系
OrientDB使用EMBEDDED
类型表示这种关系。
1:n和n:n嵌入关系
OrientDB使用链接集合表达这些关系,例如:
EMBEDDEDLIST
有序的记录列表。EMBEDDEDSET
无序记录集合,保证唯一性。EMBEDDEDMAP
有序的链接映射表,String
作为键的类型。重复的键不能接受。
反向关系
OrientDB中,图模型中的边都是双向的。这和文档模型是有区别的,文档模型中,边都是单向的,需要开发人员保证数据的完整性。另外,OrientDB自动维护所有双向关系的一致性。
数据库
数据库是访问真正的存储的接口存储。开发人员懂得高层次的概念,例如查询,模式,元数据(metadata),索引等等。OrientDB也提供多种数据库类型。更多类型,参考数据库类型.
每个服务器或者JVM都可以处理多个数据库实例,但是数据库的名字必须是唯一的。你不能同时管理两个同名的数据库,即使他们在不同的目录下。为了解决这个问题,可以使用$
作为分隔符替换/
。OrientDB绑定这个名字,所以变成唯一的。但是文件系统级别会将$
转化为/
, 允许不同路径下的数据库名称相同。例如,
test$customers -> test/customers
production$customers = production/customers
打开数据库,使用下面的代码:
test = new ODatabaseDocumentTx("remote:localhost/test$customers");
production = new ODatabaseDocumentTx("remote:localhost/production$customers");
数据库URL
OrientDB使用它自己的 URL格式:<engine>:<db-name>
.
引擎 | 描述 | 举例 |
---|---|---|
plocal | 这个引擎存储数据到文件系统中。记录变更日志在崩溃的时候恢复存储。 | plocal:/temp/databases/petshop/petshop |
memory | 完全在内存 | memory:petshop |
remote | 这个存储通过一个远程网络连接打开。需要一个启动运行的OrientDB服务器。这种模式下,数据库被多个客户端共享。语法:remote:<server>:[<port>]/db-name 。端口是可选的,默认值2424。 |
remote:localhost/petshop |
数据库使用
当你完成工作后,可以一直关闭数据库。
注意: 当进程被优雅的关闭时,OrientDB会自动关闭所有打开的数据库(强制关闭不行)。 这需要操作系统支持优雅的关闭。