Schema
While OrientDb can work in a schema-less mode, you may find it necessary at times to enforce a schema on your data model. OrientDB supports both schema-full and schema-hybrid solutions.
In the case of schema-hybrid mode, you only set constraints for certain fields and leave the user to add custom fields to the record. This mode occurs at a class level, meaning that you can have an Employee
class as schema-full and an EmployeeInformation
class as schema-less.
- Schema-full Enables strict-mode at a class-level and sets all fields as mandatory.
- Schema-less Enables classes with no properties. Default is non-strict-mode, meaning that records can have arbitrary fields.
- Schema-hybrid Enables classes with some fields, but allows records to define custom fields. This is also sometimes called schema-mixed.
NOTE Changes to the schema are not transactional. You must execute these commands outside of a transaction.
You can access the schema through SQL or through the Java API. Examples here use the latter. To access the schema API in Java, you need the Schema instance of the database you want to use. For example,
OSchema schema = database.getMetadata().getSchema();
Class
OrientDB draws from the Object Oriented programming paradigm in the concept of the Class. A class is a type of record. In comparison to Relational database systems, it is most similar in conception to the table.
Classes can be schema-less, schema-full or schema-hybrid. They can inherit from other classes, shaping a tree of classes. In other words, a sub-class extends the parent class, inheriting all attributes.
Each class has its own clusters. By default, these clusters are logical, but they can also be physical. A given class must have at least one cluster defined as its default, but it can support multiple clusters. OrientDB writes new records into the default cluster, but always reads from all defined clusters.
When you create a new class, OrientDB creates a default physical cluster that uses the same name as the class, but in lowercase.
Creating Persistent Classes
Classes contain one or more properties. This mode is similar to the classical model of the Relational database, where you must define tables before you can begin to store records.
To create a persistent class in Java, use the createClass()
method:
OClass account = database.getMetadata().getSchema().createClass("Account");
This method creates the class Account
on the database. It simultaneously creates the physical cluster account
, to provide storage for records in the class Account
.
Getting Persistent Classes
With the new persistent class created, you may also need to get its contents.
To retrieve a persistent class in Java, use the getClass()
method:
OClass account = database.getMetadata().getSchema().getClass("Account");
This method retrieves from the database the persistent class Account
. If the query finds that the Account
class does not exist, it returns NULL
.
Dropping Persistent Classes
In the event that you no longer want the class, you can drop, or delete, it from the database.
To drop a persistent class in Java, use the OSchema.dropClass()
method:
database.getMetadata().getSchema().dropClass("Account");
This method drops the class Account
from your database. It does not delete records that belong to this class unless you explicitly ask it to do so:
database.command(new OCommandSQL("DELETE FROM Account")).execute();
database.getMetadata().getSchema().dropClass("Account");
Constraints
Working in schema-full mode requires that you set the strict mode at the class-level, by defining the setStrictMode()
method to TRUE
. In this case, records of that class cannot have undefined properties.
Properties
In OrientDB, a property is a field assigned to a class. For the purposes of this tutorial, consider Property and Field as synonymous.
Creating Class Properties
After you create a class, you can define fields for that class. To define a field, use the createProperty()
method.
OClass account = database.getMetadata().getSchema().createClass("Account");
account.createProperty("id", OType.Integer);
account.createProperty("birthDate", OType.Date);
These lines create a class Account
, then defines two properties id
and birthDate
. Bear in mind that each field must belong to one of the supported types. Here these are the integer and date types.
Dropping Class Properties
In the event that you would like to remove properties from a class you can do so using the dropProperty()
method under OClass
.
database.getMetadata().getSchema().getClass("Account").dropProperty("name");
When you drop a property from a class, it does not remove records from that class unless you explicitly ask for it, using the UPDATE... REMOVE
statements. For instance,
database.getMetadata().getSchema().getClass("Account").dropProperty("name");
database.command(new OCommandSQL("UPDATE Account REMOVE name")).execute();
The first method drops the property from the class. The second updates the database to remove the property.
Relationships
OrientDB supports two types of relationships: referenced and embedded.
Referenced Relationships
In the case of referenced relationships, OrientDB uses a direct link to the referenced record or records. This allows the database to avoid the costly JOIN
operations used by Relational databases.
customer
Record A -------------> Record B
CLASS=Invoice CLASS=Customer
RID=5:23 RID=10:2
In the example, Record A contains the reference to Record B in the property customer
. Both records are accessible by any other records since each has a Record ID.
1:1 and n:1 Reference Relationships
In one to one and many to one relationships, the reference relationship is expressed using the LINK
type. For instance.
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);
Here, records of the class Invoice
link to a record of the class Customer
, through the field customer
.
1:n and n:n Reference Relationships.
In one to many and many to many relationships, OrientDB expresses the referenced relationship using collections of links.
LINKLIST
An ordered list of links.LINKSET
An unordered set of links, that does not accept duplicates.LINKMAP
An ordered map of links, with a string key. It does not accept duplicate keys.
For example,
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);
Here, you have two classes: Order
and OrderItem
and a 1:n referenced relationship is created between them.
Embedded Relationships
In the case of embedded relationships, OrientDB contains the relationship within the record. Embedded relationships are stronger than referenced relationships, but the embedded record does not have its own Record ID. Because of this, you cannot reference them directly through other records. The relationship is only accessible through the container record. If the container record is deleted, then the embedded record is also deleted.
address
Record A <>----------> Record B
CLASS=Account CLASS=Address
RID=5:23 NO RID!
Here, Record A contains the entirety of Record B in the property address
. You can only reach Record B by traversing the container, Record A.
orientdb> SELECT FROM Account WHERE Address.city = 'Rome'
1:1 and n:1 Embedded Relationships
For one to one and many to one embedded relationships, OrientDB uses links of the EMBEDDED
type. For example,
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);
Here, records of the class Account
embed records for the class Address
.
1:n and n:n Embedded Relationships
In the case of one to many and many to many relationships, OrientDB sues a collection embedded link types:
EMBEDDEDLIST
An ordered list of records.EMBEDDEDSET
An unordered set of records. It doesn't accept duplicates.EMBEDDEDMAP
An ordered map of records as key-value pairs. It doesn't accept duplicate keys.
For example,
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);
This establishes a one to many relationship between the classes Order
and OrderItem
.
Constraints
OrientDB supports a number of constraints for each field. For more information on setting constraints, see the ALTER PROPERTY
command.
- Minimum Value:
setMin()
The field accepts a string, because it works also for date ranges. - Maximum Value:
setMax()
The field accepts a string, because it works also for date rangers. - Mandatory:
setMandatory()
This field is required. - Read Only:
setReadonly()
This field cannot update after being created. - Not Null:
setNotNull()
This field cannot be null. - Unique: This field doesn't allow duplicates or speedup searches.
- Regex: This field must satisfy Regular Expressions
For example,
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");
Indices as Constraints
To define a property value as unique, use the UNIQUE
index constraint. For example,
profile.createIndex("EmployeeId", OClass.INDEX_TYPE.UNIQUE, "id");
You can also constrain a group of properties as unique by creating a composite index made from multiple fields. For instance,
profile.createIndex("compositeIdx", OClass.INDEX_TYPE.NOTUNIQUE, "name", "surname");
For more information about indexes look at Index guide.