模式(schema)

OrientDB可以无模式下工作,但是你也可以针对你的数据模型强制设定模式。OrientDB支持全模式和混合模式的情况。

在混合模式下,你只需要针对特定的字段设置约束,然后允许用户自定义加入字段。模式的定义是在类级别,意思就是你可以拥有一个全模式的Employee类和无模式的EmployeeInformation类。

  • Schema-full 类级别的严格模式,所有字段都强制约束。
  • Schema-less 类可以没有属性。模式是非严格模式,意味着记录可以有任意的字段。
  • Schema-hybrid 类可以有一些属性,允许记录自定义字段。有时也叫混合模式。

注意 模式的改变不是事务的。需要在事务外执行这些命令。

你可以通过SQL或者JAVA API查询模式。JAVA API的例子如下:

OSchema schema = database.getMetadata().getSchema();

Class

OrientDB类的概念来自于面向对象编程。一个类就是记录的定义,类似于关系数据库中的表。

类可以是schema-less, schema-full或者schema-hybrid。类可以继承其他类,形成一个类的树。换句话说,子类继承父类,继承所有属性。

每个类都有自己的簇。默认的,这些簇可以是逻辑上的,也可以是物理(类似逻辑视图和物理视图的意思)的。一个类默认至少属于一个默认的簇,也可以数以多个簇。OrientDB将记录写入默认的簇,但是会从所有的簇中读取。

当你创建一个新类时,OrientDB会创建一个物理簇,使用类的名称,小写。

创建持久化的类

类包含一个或者多个属性。这类似与关系数据库的经典模型,在存储记录之前需要定义表。

在JAVA中创建一个持久化的类,使用createClass()方法:

OClass account = database.getMetadata().getSchema().createClass("Account");

这个方法在数据库中创建类Account。同时创建物理簇account来存储类Account的记录。

获取持久化的类

类创建完毕后,使用getClass()方法可以拿到它的内容:

OClass account = database.getMetadata().getSchema().getClass("Account");

如果Account不存在,返回NULL

删除持久化类

如果你不需要类,可以从数据库中删除。Java API使用OSchema.dropClass()方法:

database.getMetadata().getSchema().dropClass("Account");

这个方法不会删除这个类的记录,除非你显式指定删除:

database.command(new OCommandSQL("DELETE FROM Account")).execute();
database.getMetadata().getSchema().dropClass("Account");

约束

通过setStrictMode()方法设置为TRUE指定schema-full模式。这种情况下,记录不允许有自定义属性。

属性

OrientDB中,属性就是类的字段。

创建类的属性

类创建之后,通过createProperty()方法定义属性:

OClass account = database.getMetadata().getSchema().createClass("Account");
account.createProperty("id", OType.Integer);
account.createProperty("birthDate", OType.Date);

上述的代码创建一个类Account,定义了两个属性idbirthDate。牢记每个属性都必须对一个支持的类型。这里使用了整型和日期类型。

删除类属性

可以使用OClassdropProperty()方法。

database.getMetadata().getSchema().getClass("Account").dropProperty("name");

删除类的属性,不会删除记录的字段,使用UPDATE... REMOVE语句来删:

database.getMetadata().getSchema().getClass("Account").dropProperty("name");
database.command(new OCommandSQL("UPDATE Account REMOVE name")).execute();

第一个方法从类中删除属性。第二个方法从库里删除属性。

关系

OrientDB支持两种类型关系: 引用和嵌入。

引用关系

OrientDB使用直接连接指向引用的记录。这使数据可避免了关系数据库中耗时的JOIN操作。

                  customer
  Record A     ------------->    Record B
CLASS=Invoice                 CLASS=Customer
  RID=5:23                       RID=10:2

上面的例子,记录A在属性customer包含了记录B的引用。 记录之间可以通过Record ID相互访问。

1:1 and n:1 引用关系

在1对1和多对1的关系中,引用使用LINK类型来表示。例如:

OClass customer= database.getMetadata().getSchema().createClass("Customer");
customer.createProperty("name", OType.STRING);

OClass invoice = database.getMetadata().getSchema().createClass("Invoice");
invoice.createProperty("id", OType.INTEGER);
invoice.createProperty("date", OType.DATE);
invoice.createProperty("customer", OType.LINK, customer);

这里,类Invoice的记录通过属性customer连接类Customer

1:nn:n引用关系.

在1对多和多对多的关系中,OrientDB使用集合连接来表示。

  • LINKLIST 有序的链接列表。
  • LINKSET 无序的链接集合,保证唯一性。
  • LINKMAP 有序的链接映射表,String作为键的类型。重复的键不能接受。

例如,

OClass orderItem = db.getMetadata().getSchema().createClass("OrderItem");
orderItem.createProperty("id", OType.INTEGER);
orderItem.createProperty("animal", OType.LINK, animal);

OClass order = db.getMetadata().getSchema().createClass("Order");
order.createProperty("id", OType.INTEGER);
order.createProperty("date", OType.DATE);
order.createProperty("items", OType.LINKLIST, orderItem);

这里, OrderOrderItem就是1:n的引用关系。

嵌入关系

针对嵌入关系,OrientDB直接包含了对应的记录。嵌入式的记录没有自己的记录ID, 所以你无法通过其他记录直接访问。但是可以通过容器记录(嵌入它的记录)访问。这种情况下,你删除容器记录,嵌入的记录也会被删除。例如,

                  address
  Record A     <>---------->   Record B
CLASS=Account               CLASS=Address
  RID=5:23                     NO RID!

这里,记录A将整个记录B的信息放在属性address。你只有通过访问记录A来查询记录B。

orientdb> SELECT FROM Account WHERE Address.city = 'Rome'

1:1 and n:1嵌入关系

对于1对1和多对1的嵌入关系,OrientDB使用EMBEDDED类型. 例如,

OClass address = database.getMetadata().getSchema().createClass("Address");

OClass account = database.getMetadata().getSchema().createClass("Account");
account.createProperty("id", OType.INTEGER);
account.createProperty("birthDate", OType.DATE);
account.createProperty("address", OType.EMBEDDED, address);

这里,类Account的记录嵌入类Address的记录。

1:nn:n嵌入关系

在1对多和多对多的情况下,OrientDB使用embedded集合类型:

  • EMBEDDEDLIST 有序的记录列表.
  • EMBEDDEDSET 无需的记录集合,保证唯一性。
  • EMBEDDEDMAP 有序的记录Map,保证key的唯一性。

例如,

OClass orderItem = db.getMetadata().getSchema().createClass("OrderItem");
orderItem.createProperty("id", OType.INTEGER);
orderItem.createProperty("animal", OType.LINK, animal);

OClass order = db.getMetadata().getSchema().createClass("Order");
order.createProperty("id", OType.INTEGER);
order.createProperty("date", OType.DATE);
order.createProperty("items", OType.EMBEDDEDLIST, orderItem);

上面的代码建立了类OrderOrderItem的1对多嵌入关系。

约束

OrientDB支持针对每一个字段设置多个约束。更多信息,参考 ALTER PROPERTY命令。

  • Minimum Value: setMin() 接受字符串当做参数,也可以是日期范围。
  • Maximum Value: setMax() 接受字符串当做参数,也可以是日期范围。
  • Mandatory: setMandatory() 表明这个字段是必须的。
  • Read Only: setReadonly() 字段创建后只读。
  • Not Null: setNotNull() 字段非Null。
  • Unique: 字段不允许重复或者不能加快搜索。
  • Regex: 字段必须满足正则表达式的格式。

例如,

profile.createProperty("nick", OType.STRING).setMin("3").setMax("30").setMandatory(true).setNotNull(true);
profile.createIndex("nickIdx", OClass.INDEX_TYPE.UNIQUE, "nick"); // Creates unique constraint

profile.createProperty("name", OType.STRING).setMin("3").setMax("30");
profile.createProperty("surname", OType.STRING).setMin("3").setMax("30");
profile.createProperty("registeredOn", OType.DATE).setMin("2010-01-01 00:00:00");
profile.createProperty("lastAccessOn", OType.DATE).setMin("2010-01-01 00:00:00");

索引约束

定义属性唯一,使用唯一性索引约束UNIQUE。例如,

profile.createIndex("EmployeeId", OClass.INDEX_TYPE.UNIQUE, "id");

你可以针对一组属性创建组合唯一索引。例如,

profile.createIndex("compositeIdx", OClass.INDEX_TYPE.NOTUNIQUE, "name", "surname");

更多信息参考索引.