模式(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
,定义了两个属性id
和birthDate
。牢记每个属性都必须对一个支持的类型。这里使用了整型和日期类型。
删除类属性
可以使用OClass
的dropProperty()
方法。
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:n和n: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);
这里, Order
和OrderItem
就是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:n和n: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);
上面的代码建立了类Order
和OrderItem
的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");
更多信息参考索引.