OrientDB Manual Orient DB Manual(3.X)

User Manual: Pdf

Open the PDF directly: View PDF PDF.
Page Count: 1452

DownloadOrientDB Manual Orient DB-Manual(3.X)
Open PDF In BrowserView PDF
Table of Contents
Home

1.1

FIRST STEPS
Introduction

2.1

About This M anual

2.1.1

Overview of OrientDB

2.1.2

Editions
Release 3.0

2.1.2.1
2.1.3

What's new in OrientDB 3.0?

2.1.3.1

Available Packages

2.1.3.2

SQL Changes

2.1.3.3

API Changes

2.1.3.4

Known Issues

2.1.3.5

Upgrading to OrientDB 3.0

2.1.3.6

How to Report Bugs or Problems

2.1.4

How to Get in Touch with OrientDB

2.1.5

How to Contribute to OrientDB

2.1.6

OrientDB Roadmap

2.1.7

OrientDB in Five M inutes

2.2

Install

2.2.1

Create a DB

2.2.2

Create the Java Application

2.2.3

Connect to the DB and create the Schema

2.2.4

Create your First Graph and Run Queries

2.2.5

Getting Started

2.3

Installation

2.3.1

Run the server

2.3.2

Run the console

2.3.3

Run the Studio

2.3.4

Documents, Vertices and Edges

2.3.5

Classes, Schema and Constraints

2.3.6

Demo Database

2.3.7

Introduction

2.3.7.1

Data M odel

2.3.7.2

Queries

2.3.7.3

Profiles

2.3.7.3.1

Friendship

2.3.7.3.2

Customers

2.3.7.3.3

Countries

2.3.7.3.4

Orders

2.3.7.3.5

1

Attractions

2.3.7.3.6

Services

2.3.7.3.7

Locations

2.3.7.3.8

Reviews

2.3.7.3.9

Recommendations

2.3.7.3.10

Business Opportunities

2.3.7.3.11

Polymorphism

2.3.7.3.12

Shortest Paths

2.3.7.3.13

Traverses

2.3.7.3.14

Graph Portions

2.3.7.4

Basic SQL

2.3.8

Users, Roles and Security

2.3.9

Distributed Architecture

2.3.10

Tutorials

2.3.11

Working with Graphs

2.3.11.1

Using Schema with Graphs

2.3.11.2

Setup a Distributed Database

2.3.11.3

Working with Distributed Graphs

2.3.11.4

Time Series

2.3.11.5

Chat

2.3.11.6

Key Value

2.3.11.7

Queue system

2.3.11.8

Import Tutorials

2.3.11.9

Importing the Open Beer Database into OrientDB

2.3.11.9.1

Importing the northwind Database from Neo4j

2.3.11.9.2

Importing the movie Database from Neo4j

2.3.11.9.3

General Information

2.4

Supported Types

2.4.1

Schema

2.4.2

Inheritance

2.4.3

Concurrency

2.4.4

Indexing

2.4.5

SB-Tree

2.4.5.1

Hash

2.4.5.2

Auto-Sharding

2.4.5.3

Full Text

2.4.5.4

Lucene Full Text

2.4.5.5

Lucene Spatial Index

2.4.5.6

M anaging Dates

2.4.6

Transactions

2.4.7

Embedding the Server

2.4.8

Available OrientDB Plugins

2.4.9

Automatic Backup

2.4.9.1

SysLog

2.4.9.2

2

M ail

2.4.9.3

JM X

2.4.9.4

Rexster

2.4.9.5

Gephi Graph Render

2.4.9.6

spider-box

2.4.9.7

3rd Party Plugins

2.4.9.8

Data M odeling

2.5

M ulti Tenant

2.5.1

Basic Concepts

2.5.2

CORE TOPICS
OrientDB Programs

3.1

OrientDB Server-Startup Programs

3.1.1

server

3.1.1.1

dserver

3.1.1.2

orientdb

3.1.1.3

OrientDB Client Programs
Console

3.1.2
3.1.2.1

Console M odes

3.1.2.1.1

Console Commands

3.1.2.1.2

Backup

3.1.2.1.2.1

Browse Class

3.1.2.1.2.2

Browse Cluster

3.1.2.1.2.3

List Classes

3.1.2.1.2.4

Cluster Status

3.1.2.1.2.5

List Clusters

3.1.2.1.2.6

List Servers

3.1.2.1.2.7

List Server Users

3.1.2.1.2.8

Check Database

3.1.2.1.2.9

Config

3.1.2.1.2.10

Config Get

3.1.2.1.2.11

Config Set

3.1.2.1.2.12

Connect

3.1.2.1.2.13

Create Database

3.1.2.1.2.14

Declare Intent

3.1.2.1.2.15

Dictionary Get

3.1.2.1.2.16

Dictionary Keys

3.1.2.1.2.17

Dictionary Put

3.1.2.1.2.18

Dictionary Remove

3.1.2.1.2.19

Disconnect

3.1.2.1.2.20

Display Record

3.1.2.1.2.21

Display Raw Record

3.1.2.1.2.22

Drop Database

3.1.2.1.2.23

Drop Server User

3.1.2.1.2.24

3

Export Database

3.1.2.1.2.25

Export Record

3.1.2.1.2.26

Freeze DB

3.1.2.1.2.27

Get

3.1.2.1.2.28

Import Database

3.1.2.1.2.29

Indexes

3.1.2.1.2.30

Info

3.1.2.1.2.31

Info Class

3.1.2.1.2.32

Info Property

3.1.2.1.2.33

Js

3.1.2.1.2.34

Jss

3.1.2.1.2.35

List Databases

3.1.2.1.2.36

List Connections

3.1.2.1.2.37

Load Record

3.1.2.1.2.38

Load Script

3.1.2.1.2.39

Profiler

3.1.2.1.2.40

Properties

3.1.2.1.2.41

Release DB

3.1.2.1.2.42

Reload Record

3.1.2.1.2.43

Repair Database

3.1.2.1.2.44

Restore

3.1.2.1.2.45

Set

3.1.2.1.2.46

Set Server User

3.1.2.1.2.47

Custom Console Commands
OrientDB Administrative and Utility Programs

3.1.2.1.3
3.1.3

backup

3.1.3.1

shutdown

3.1.3.2

stresstester

3.1.3.3

OrientDB Data Import Programs

3.1.4

orientdb-neo4j-importer

3.1.4.1

oetl

3.1.4.2

OrientDB Server Administration
Installation

3.2
3.2.1

Prerequisites

3.2.1.1

Installation from Source

3.2.1.2

Install as Service on Unix

3.2.1.3

Install as Service on Windows

3.2.1.4

Install with Docker

3.2.1.5

Configuration

3.2.2

Upgrade

3.2.3

Backward Compatibility

3.2.3.1

Upgrading a Distributed Environment

3.2.3.2

Logs

3.2.4

Event Scheduler

3.2.5

4

Functions

3.2.6

Creating Functions

3.2.6.1

Using Functions

3.2.6.2

Accessing the Database

3.2.6.3

Server-side Functions

3.2.6.4

Backup and Restore
Incremental Backup and Restore
Export and Import

3.2.7
3.2.7.1
3.2.8

Export to & Import from JSON
Export format
Import From RDBM S

3.2.8.1
3.2.8.1.1
3.2.8.2

To Document M odel

3.2.8.2.1

To Graph M odel

3.2.8.2.2

Import From Neo4j
Import from Neo4j using GraphM L
M onitoring

3.2.8.3
3.2.8.3.1
3.2.9

JM X

3.2.9.1

OrientDB Tools

3.3

Studio

3.3.1

Introduction

3.3.1.1

Overview of M enus and Panels

3.3.1.2

Working with Databases

3.3.1.3

Common Database Operations

3.3.1.3.1

Database M anagement Panel

3.3.1.3.2

Working with Data

3.3.1.4

Browse Panel

3.3.1.4.1

Querying Data

3.3.1.4.1.1

M odifying Data

3.3.1.4.1.2

Edit Document

3.3.1.4.1.2.1

Edit Vertex

3.3.1.4.1.2.2

Edit Edge

3.3.1.4.1.2.3

Graph Editor
Working with Schemas

3.3.1.4.2
3.3.1.5

Schema M anager Panel

3.3.1.5.1

Classes

3.3.1.5.2

Properties

3.3.1.5.3

Indexes

3.3.1.5.4

Working with Functions
Functions M anagement Panel
Working with Users and Roles

3.3.1.6
3.3.1.6.1
3.3.1.7

Security M anager Panel

3.3.1.7.1

Users M anagement

3.3.1.7.2

Roles M anagement

3.3.1.7.3

Backups, Imports and Exports

3.3.1.8

5

Backup M anagement Panel

3.3.1.8.1

Integration with Teleporter

3.3.1.8.2

Integration with the Neo4j to OrientDB Importer

3.3.1.8.3

Server M anagement

3.3.1.9

Dashboard Panel

3.3.1.9.1

Servers M anagement Panel

3.3.1.9.2

Cluster M anagement Panel

3.3.1.9.3

Data Centers

3.3.1.9.3.1

Query Profiler Panel

3.3.1.9.4

Security Panel

3.3.1.9.5

Server Auditing
Alerts M anagement Panel

3.3.1.9.5.1
3.3.1.9.6

Studio Backup M anagement

3.3.1.10

Teleporter

3.3.1.11

Neo4j to OrientDB Importer

3.3.1.12

Teleporter

3.3.2

Installation and configuration

3.3.2.1

Execution strategies

3.3.2.2

Sequential executions and One-Way Synchronizer

3.3.2.3

Import filters

3.3.2.4

Inheritance

3.3.2.5

Single Table Inheritance

3.3.2.5.1

Table Per Class Inheritance

3.3.2.5.2

Table Per Concrete Class Inheritance

3.3.2.5.3

Import Configuration
ETL

3.3.2.6
3.3.3

Configuration

3.3.3.1

Blocks

3.3.3.2

Sources

3.3.3.3

Extractors

3.3.3.4

Transformers

3.3.3.5

Loaders

3.3.3.6

Import from CSV to a Graph

3.3.3.7

Import a tree structure

3.3.3.8

Import from JSON

3.3.3.9

Import from RDBM S

3.3.3.10

Import from DB-Pedia

3.3.3.11

Import from Parse (Facebook)

3.3.3.12

Neo4j to OrientDB Importer

3.3.4

SQL, API, DRIVERS
SQL Reference
Introduction
Querying M etadata

4.1
4.1.1
4.1.1.1

6

SQL Syntax

4.1.2

Projections

4.1.2.1

SQL Commands

4.1.3

Alter Class

4.1.3.1

Alter Cluster

4.1.3.2

Alter Database

4.1.3.3

Alter Property

4.1.3.4

Alter Sequence

4.1.3.5

Create Class

4.1.3.6

Create Cluster

4.1.3.7

Create Edge

4.1.3.8

Create Function

4.1.3.9

Create Index

4.1.3.10

Create Link

4.1.3.11

Create Property

4.1.3.12

Create Sequence

4.1.3.13

Create User

4.1.3.14

Create Vertex

4.1.3.15

Delete

4.1.3.16

Delete Edge

4.1.3.17

Delete Vertex

4.1.3.18

Drop Class

4.1.3.19

Drop Cluster

4.1.3.20

Drop Index

4.1.3.21

Drop Property

4.1.3.22

Drop Sequence

4.1.3.23

Drop User

4.1.3.24

Explain

4.1.3.25

Find References

4.1.3.26

Grant

4.1.3.27

HA Remove Server

4.1.3.28

HA Status

4.1.3.29

HA Sync Cluster

4.1.3.30

HA Sync Database

4.1.3.31

HA Set

4.1.3.32

Insert

4.1.3.33

Live Select

4.1.3.34

Live Unsubscribe

4.1.3.35

M atch

4.1.3.36

M ove Vertex

4.1.3.37

Optimize Database

4.1.3.38

Profile

4.1.3.39

Rebuild Index

4.1.3.40

Revoke

4.1.3.41

7

Select

4.1.3.42

Traverse

4.1.3.43

Truncate Class

4.1.3.44

Truncate Cluster

4.1.3.45

Truncate Record

4.1.3.46

Update

4.1.3.47

Update Edge

4.1.3.48

Filtering

4.1.4

Functions

4.1.5

M ethods

4.1.6

Batch

4.1.7

Pagination

4.1.8

Sequences and auto increment

4.1.9

Pivoting with Query

4.1.10

Command Cache

4.1.11

APIs and Drivers

4.2

Java API

4.2.1

Java M ulti-M odel API

4.2.1.1

Database creation and connection

4.2.1.1.1

M anipulating data in Java

4.2.1.1.2

Running SQL statements Java

4.2.1.1.3

Defining Database Schema

4.2.1.1.4

Classes

4.2.1.1.4.1

Property

4.2.1.1.4.2

Reference

4.2.1.2

OClass

4.2.1.2.1

addCluster()

4.2.1.2.1.1

addClusterId()

4.2.1.2.1.2

addSuperClass()

4.2.1.2.1.3

count()

4.2.1.2.1.4

createIndex()

4.2.1.2.1.5

createProperty()

4.2.1.2.1.6

dropProperty()

4.2.1.2.1.7

existsProperty()

4.2.1.2.1.8

getAllSubclasses()

4.2.1.2.1.9

getAllSuperClasses()

4.2.1.2.1.10

getAutoShardingIndex()

4.2.1.2.1.11

getClassIndex()

4.2.1.2.1.12

getClassIndexes()

4.2.1.2.1.13

getClassInvolvedIndexes()

4.2.1.2.1.14

getClusterIds()

4.2.1.2.1.15

getDefaultClusterId()

4.2.1.2.1.16

getIndexedProperties()

4.2.1.2.1.17

getProperty()

4.2.1.2.1.18

8

getSubclasses()

4.2.1.2.1.19

getSuperClassesNames()

4.2.1.2.1.20

hasClusterId()

4.2.1.2.1.21

hasPolymorphicClusterId()

4.2.1.2.1.22

hasSuperClasses()

4.2.1.2.1.23

isEdgeType()

4.2.1.2.1.24

isVertexType()

4.2.1.2.1.25

properties()

4.2.1.2.1.26

propertiesM ap()

4.2.1.2.1.27

removeClusterId()

4.2.1.2.1.28

removeSuperClass()

4.2.1.2.1.29

setDefaultClusterId()

4.2.1.2.1.30

setName()

4.2.1.2.1.31

truncate()

4.2.1.2.1.32

truncateCluster()

4.2.1.2.1.33

ODatabaseDocument

4.2.1.2.2

browseClass()

4.2.1.2.2.1

browseCluster()

4.2.1.2.2.2

countClass()

4.2.1.2.2.3

createClass()

4.2.1.2.2.4

createClassIfNotExists()

4.2.1.2.2.5

createEdgeClass()

4.2.1.2.2.6

createVertexClass()

4.2.1.2.2.7

getRecord()

4.2.1.2.2.8

getRecordType()

4.2.1.2.2.9

newBlob()

4.2.1.2.2.10

newEdge()

4.2.1.2.2.11

newElement()

4.2.1.2.2.12

newInstance()

4.2.1.2.2.13

newVertex()

4.2.1.2.2.14

OEdge

4.2.1.2.3

getFrom()

4.2.1.2.3.1

getTo()

4.2.1.2.3.2

OElement

4.2.1.2.4

asEdge()

4.2.1.2.4.1

asVertex()

4.2.1.2.4.2

getProperty()

4.2.1.2.4.3

getPropertyNames()

4.2.1.2.4.4

getSchemaType()

4.2.1.2.4.5

isEdge()

4.2.1.2.4.6

isVertex()

4.2.1.2.4.7

removeProperty()

4.2.1.2.4.8

setProperty()

4.2.1.2.4.9

OProperty

4.2.1.2.5

9

getDefaultValue()

4.2.1.2.5.1

getM ax()

4.2.1.2.5.2

getM in()

4.2.1.2.5.3

getName()

4.2.1.2.5.4

getType()

4.2.1.2.5.5

isM andatory()

4.2.1.2.5.6

isNotNull()

4.2.1.2.5.7

setDefaultValue()

4.2.1.2.5.8

setM ax()

4.2.1.2.5.9

setM in()

4.2.1.2.5.10

setName()

4.2.1.2.5.11

setType()

4.2.1.2.5.12

OrientDB

4.2.1.2.6

create()

4.2.1.2.6.1

createIfNotExists()

4.2.1.2.6.2

drop()

4.2.1.2.6.3

exists()

4.2.1.2.6.4

list()

4.2.1.2.6.5

open()

4.2.1.2.6.6

OServer

4.2.1.2.7

addTemporaryUser()

4.2.1.2.7.1

addUser()

4.2.1.2.7.2

authenticate()

4.2.1.2.7.3

dropUser()

4.2.1.2.7.4

existsStoragePath()

4.2.1.2.7.5

getAvailableStorageNames()

4.2.1.2.7.6

getConfiguration()

4.2.1.2.7.7

getDatabaseDirectory()

4.2.1.2.7.8

getInstance()

4.2.1.2.7.9

getInstanceByPath()

4.2.1.2.7.10

getStoragePath()

4.2.1.2.7.11

isActive()

4.2.1.2.7.12

isAllowed()

4.2.1.2.7.13

openDatabase()

4.2.1.2.7.14

restart()

4.2.1.2.7.15

saveConfiguration()

4.2.1.2.7.16

shutdown()

4.2.1.2.7.17

startup()

4.2.1.2.7.18

OType

4.2.1.2.8

OVertex

4.2.1.2.9

addEdge()

4.2.1.2.9.1

getEdges()

4.2.1.2.9.2

getVertices()

4.2.1.2.9.3

TinkerPop 2.6 Graph API

4.2.1.3

10

Tutorial

4.2.1.3.1

Vertices and Edges

4.2.1.3.2

Blueprints Extension

4.2.1.3.3

Factory

4.2.1.3.4

Schema

4.2.1.3.5

Class

4.2.1.3.5.1

Property

4.2.1.3.5.2

Partitioned

4.2.1.3.6

Lightweight Edges

4.2.1.3.7

Graph Batch Insert

4.2.1.3.8

Apache TinkerPop 3

4.2.1.4

Document API

4.2.1.5

Documents
Object API

4.2.1.5.1
4.2.1.6

Database

4.2.1.6.1

POJO

4.2.1.6.2

Attach

4.2.1.6.3

Schema

4.2.1.6.4

Binding

4.2.1.6.5

Traverse

4.2.1.7

M ulti-Threading

4.2.1.8

Usage

4.2.1.8.1

Concurrency Control

4.2.1.8.2

Transactions

4.2.1.9

Fetching Strategies

4.2.1.10

Graph Consistency

4.2.1.11

Binary Data

4.2.1.12

JPA

4.2.1.13

JDBC Driver

4.2.2

Scala API

4.2.3

OrientJS - Node.js Driver

4.2.4

Server API

4.2.4.1

Database API

4.2.4.2

Record API

4.2.4.3

Class API

4.2.4.4

Class

4.2.4.4.1

Property

4.2.4.4.2

Records

4.2.4.4.3

Index API

4.2.4.5

Function API

4.2.4.6

Queries

4.2.4.7

create()

4.2.4.7.1

delete()

4.2.4.7.2

fetch()

4.2.4.7.3

11

insert()

4.2.4.7.4

liveQuery()

4.2.4.7.5

select()

4.2.4.7.6

transform()

4.2.4.7.7

traverse()

4.2.4.7.8

update()

4.2.4.7.9

Transactions

4.2.4.8

Events

4.2.4.9

PyOrient - Python Driver
Client

4.2.5
4.2.5.1

command()

4.2.5.1.1

batch()

4.2.5.1.2

data_cluster_add()

4.2.5.1.3

data_cluster_count()

4.2.5.1.4

data_cluster_data_range()

4.2.5.1.5

data_cluster_drop()

4.2.5.1.6

db_count_records()

4.2.5.1.7

db_create()

4.2.5.1.8

db_drop()

4.2.5.1.9

db_exists()

4.2.5.1.10

db_list()

4.2.5.1.11

db_open()

4.2.5.1.12

db_reload()

4.2.5.1.13

db_size()

4.2.5.1.14

get_session_token()

4.2.5.1.15

query()

4.2.5.1.16

query_async()

4.2.5.1.17

record_create()

4.2.5.1.18

record_delete()

4.2.5.1.19

record_load()

4.2.5.1.20

record_update()

4.2.5.1.21

set_session_token()

4.2.5.1.22

tx_commit()

4.2.5.1.23

attach()

4.2.5.1.23.1

begin()

4.2.5.1.23.2

commit()

4.2.5.1.23.3

rollback()

4.2.5.1.23.4

OGM

4.2.5.2

Connection

4.2.5.2.1

Schemas

4.2.5.2.2

Brokers

4.2.5.2.3

Batch

4.2.5.2.4

Scripts

4.2.5.2.5

OrientDB-NET - C#/.NET Driver

4.2.6

12

Server

4.2.6.1

ConfigGet()

4.2.6.1.1

ConfigList()

4.2.6.1.2

ConfigSet()

4.2.6.1.3

CreateDatabase()

4.2.6.1.4

DatabaseExists()

4.2.6.1.5

Databases()

4.2.6.1.6

DropDatabase()

4.2.6.1.7

Database

4.2.6.2

Clusters()

4.2.6.2.1

Command()

4.2.6.2.2

GetClusterIdFor()

4.2.6.2.3

GetClusterNameFor()

4.2.6.2.4

GetClusters()

4.2.6.2.5

Gremlin()

4.2.6.2.6

Insert()

4.2.6.2.7

JavaScript()

4.2.6.2.8

Query()

4.2.6.2.9

Select()

4.2.6.2.10

SqlBatch()

4.2.6.2.11

Update()

4.2.6.2.12

Query

4.2.6.3

Conditionals

4.2.6.3.1

Limiters

4.2.6.3.2

Sort

4.2.6.3.3

Transaction

4.2.6.4

Add()

4.2.6.4.1

AddEdge()

4.2.6.4.2

AddOrUpdate()

4.2.6.4.3

Delete()

4.2.6.4.4

GetPendingObject()

4.2.6.4.5

Update()

4.2.6.4.6

PhpOrient - PHP Driver

4.2.7

Client

4.2.7.1

Server

4.2.7.2

dbCreate()

4.2.7.2.1

dbDrop()

4.2.7.2.2

dbExists()

4.2.7.2.3

dbList()

4.2.7.2.4

Database

4.2.7.3

command()

4.2.7.3.1

dataClusterAdd()

4.2.7.3.2

dataClusterCount()

4.2.7.3.3

dataClusterDrop()

4.2.7.3.4

13

dataClusterDataRange()

4.2.7.3.5

dbCountRecords()

4.2.7.3.6

dbReload()

4.2.7.3.7

dbSize()

4.2.7.3.8

query()

4.2.7.3.9

queryAsync()

4.2.7.3.10

recordCreate()

4.2.7.3.11

recordLoad()

4.2.7.3.12

recordUpdate()

4.2.7.3.13

sqlBatch()

4.2.7.3.14

ClusterM ap

4.2.7.4

dropClusterID()

4.2.7.4.1

getClusterID()

4.2.7.4.2

getIdList()

4.2.7.4.3

Record

4.2.7.5

getOClass()

4.2.7.5.1

getOData()

4.2.7.5.2

getRid()

4.2.7.5.3

jsonSerialize()

4.2.7.5.4

recordSerialize()

4.2.7.5.5

setOClass()

4.2.7.5.6

setOData()

4.2.7.5.7

setRid()

4.2.7.5.8

ID

4.2.7.6

Transaction

4.2.7.7

attach()

4.2.7.7.1

begin()

4.2.7.7.2

commit()

4.2.7.7.3

rollback()

4.2.7.7.4

M arcoPolo - Elixir Driver
Server

4.2.8
4.2.8.1

create_db()

4.2.8.1.1

db_exists?()

4.2.8.1.2

distrib-config()

4.2.8.1.3

drop_db()

4.2.8.1.4

Database

4.2.8.2

command()

4.2.8.2.1

create_record()

4.2.8.2.2

db_countrecords()

4.2.8.2.3

db_reload()

4.2.8.2.4

db_size()

4.2.8.2.5

delete_record()

4.2.8.2.6

live_query()

4.2.8.2.7

live_query_unsubscribe()

4.2.8.2.8

14

load_record()

4.2.8.2.9

script()

4.2.8.2.10

update_record()

4.2.8.2.11

Types

4.2.8.3

Structs

4.2.8.4

BinaryRecord

4.2.8.4.1

Date

4.2.8.4.2

DateTime

4.2.8.4.3

Document

4.2.8.4.4

FetchPlan

4.2.8.4.5

RID

4.2.8.4.6

Javascript (legacy)
Javascript API

4.2.9
4.2.9.1

Rest API

4.2.10

Gremlin API

4.2.11

ADVANCED TOPICS
Security

5.1

Database security

5.1.1

Server security

5.1.2

Database encryption

5.1.3

Secure SSL connections

5.1.4

Security Configuration

5.1.5

Kerberos Example

5.1.6

Security v2.2 Code Changes

5.1.7

Security v2.2 New Features

5.1.8

Symmetric Key Authentication

5.1.9

Distributed Architecture

5.2

Lifecycle

5.2.1

Configuration

5.2.2

Server M anager

5.2.2.1

Runtime Configuration

5.2.2.2

Replication

5.2.3

Sharding

5.2.4

Data Centers

5.2.5

Troubleshooting

5.3

Java

5.3.1

M emory Leak Detector

5.3.2

Direct M emory Tracing

5.3.3

Performance Tuning

5.4

Tuning the Graph API

5.4.1

Tuning the Document API

5.4.2

Tuning the Object API

5.4.3

Profiler

5.4.4

15

Distributed Configuration Tuning

5.4.5

OrientDB Stress Test Tool

5.4.6

Enterprise Edition
Auditing

5.5
5.5.1

Internals

6.1

System database

6.1.1

Storages

6.1.2

M emory storage

6.1.2.1

PLocal storage

6.1.2.2

Engine

6.1.2.2.1

Disk-Cache

6.1.2.2.2

WAL (Journal)

6.1.2.2.3

Local storage (deprecated)

6.1.2.3

Clusters

6.1.3

Limits

6.1.4

RidBag

6.1.5

Custom Index Engine

6.1.6

Caching

6.1.7

Hooks - Triggers

6.1.8

Dynamic Hooks

6.1.8.1

Java (Native) Hooks

6.1.8.2

Server
Server Status

6.1.9
6.1.9.1

Web Server

6.1.10

Binary Protocol

6.1.11

CSV Serialization

6.1.11.1

Schemaless Serialization

6.1.11.2

Commands

6.1.11.3

Release Notes

7.1

16

Home

OrientDB Manual - version 3.0.0RC1

Welcome to OrientDB - the first M ulti-M odel Open Source NoSQL DBM S that brings together the power of graphs and the flexibility
of documents into one scalable high-performance operational database.

OrientDB 3.0 M2 is out!
Check what's new and download the binary distribution now

OrientDB 3.0.0RC1 and this M anual are still in development. Not suitable for production
environments.

Quick Navigation
Getting S tarted

Main Topics

Developers

Introduction to OrientDB

Basic Concepts

SQL

Installation

Supported Data Types

Gremlin

First Steps

Inheritance

HTTP API

Troubleshooting

Security

Java API

Enterprise Edition

Indexes

NodeJS

ACID Transactions

PHP

Functions

Python

Caching Levels

.NET

Common Use Cases

Other Drivers
Network Binary Protocol
Javadocs

17

Home

Operations
Installation
3rd party Plugins
Upgrade
Configuration
Distributed Architecture (replication, sharding and high-availability)
Performance Tuning
ETL to Import any kind of data into OrientDB
Import from Relational DB
Backup and Restore
Export and Import

Quick References
Console
Studio web tool
OrientDB Server
Network-Binary-Protocol
Gephi Graph Analysis Visual tool
Rexster Support and configuration
Continuous integration

Resources
User Group - Have question, troubles, problems?
#orientdb IRC channel on freenode
Professional Support
Training - Training and classes.
Events - Follow OrientDB at the next event!
Team - M eet the team behind OrientDB
Contribute - Contribute to the project.
Who is using OrientDB? - Clients using OrientDB in production.

Questions or Need Help?
Check out our Get in Touch page for different ways of getting in touch with us.

PDF
This documentation is also available in PDF format.

Past Releases
v2.2.x
v2.1.x
v2.0.x
v1.7.8
Every effort has been made to ensure the accuracy of this manual. However, OrientDB, LTD. makes no warranties with respect
to this documentation and disclaims any implied warranties of merchantability and fitness for a particular purpose. The
information in this document is subject to change without notice.

18

Introduction

Introduction
This Chapter provides an introduction to OrientDB.
About This M anual
Overview of OrientDB
Release 3.0
What's new in OrientDB 3.0?
Available Packages
SQL Changes
API Changes
Known Issues
Upgrading to OrientDB 3.0
How to Report Bugs or Problems
How to Get in Touch with OrientDB
How to Contribute to OrientDB
OrientDB Roadmap

19

About This M anual

About this Manual
This M anual documents version 3.0 of the OrientDB Server and the OrientDB suite of products.

OrientDB 3.0.0RC1 and this M anual are still in development.

Generated on M on Jan 08 2018 10:25:34 GM T+0000 (UTC) using GitBook v.3.2.2.

20

Overview of OrientDB

Overview
OrientDB is the first M ulti-M odel Open Source NoSQL DBM S that combines the power of graphs and the flexibility of documents
into one scalable, high-performance operational database.
Gone are the days where your database only supports a single data model. As a direct response to polyglot persistence, multi-model
databases acknowledge the need for multiple data models, combining them to reduce operational complexity and maintain data
consistency. Though graph databases have grown in popularity, most NoSQL products are still used to provide scalability to
applications sitting on a relational DBM S. Advanced 2nd generation NoSQL products like OrientDB are the future: providing more
functionality and flexibility, while being powerful enough to replace your operational DBM S.

Speed
OrientDB was engineered from the ground up with performance as a key specification. It’s fast on both read and write operations.
Stores up to 120,000 records per second
No more Joins: relationships are physical links to the records.
Better RAM use.
Traverses parts of or entire trees and graphs of records in milliseconds.
Traversing speed is not affected by the database size.

Enterprise
While most NoSQL DBM Ss are used as secondary databases, OrientDB is powerful and flexible enough to be used as an operational
DBM S. Though OrientDB Community Edition is free for commercial use, robust applications need enterprise level functionalities to
guarantee data security and flawless performance. OrientDB Enterprise Edition gives you all the features of our community edition plus:
Incremental backups
Unmatched security
24x7 Support
Query Profiler
Distributed Clustering configuration
M etrics Recording
Live M onitor with configurable alerts

Zero Configuration Multi-Master Architecture
With a master-slave architecture, the master often becomes the bottleneck. With OrientDB, throughput is not limited by a single server.
Global throughput is the sum of the throughput of all the servers.
M ulti-M aster + Sharded architecture
Elastic Linear Scalability
Restore the database content using WAL
With a zero-config multi-master architecture, OrientDB is perfect for the Cloud. Hundreds of servers can share the workload, scaling
horizontally across distributed modern data centers.

Flexibility
Replacing your DBM S, once it no longer meets requirements, can be a huge cost in time and resources. Is your database powerful,
scalable and flexible enough to grow with you? Using OrientDB also reduces the need to support multiple products to achieve your
goals.

21

Overview of OrientDB

Get Started in Minutes
OrientDB is written entirely in Java and can run on any platform without configuration and installation. It's a drop-in replacement for
the most common existing graph databases in deployment today.
2M B Full Server distribution (not including demo)
M ultiple Programming Language Bindings
Extended SQL with graph functionality
Tinkerpop API
Coming from the relational world? Import your data using OrientDB Teleporter and get started in an instant
Coming From Neo4j? Our Neo4j Importer lets you get started with your own graph data

Low TCO
There is absolutely no cost associated with using OrientDB Community Edition.
OrientDB Community is free for commercial use.
Comes with an Apache 2 Open Source License.
Eliminates the need for multiple products and multiple licenses.
OrientDB Ltd, the company behind OrientDB, offers optional services such as Developer and Production Support, consultancy and
Training with transparent pricing far below our competitors to ensure you’re maximizing OrientDB’s capabilities for your particular use
case. OrientDB Enterprise Edition is included with the purchase of any of these services.

Open Source
Which is more likely to have better quality? A DBM S created and tested by a handful of developers or one tested by over 100,000
developers globally? When code is public, everyone can scrutinize, test, report and resolve issues. All things Open Source move faster
compared to the proprietary world. In fact, the most popular databases ranked by DB-Engines are now Open Source.
OrientDB LTD leads the OrientDB Open Source project and defines the roadmap but all members of the OrientDB Development Team
were original contributors to the OrientDB Open Source project, years before being brought onto the team. Their expert product
knowledge coupled with the passion they bring to the table every day, ensures quality for our products, support and consultancy work.

22

Editions

Editions
OrientDB is available in two editions:
Community Edition is released as an open source project under the Apache 2 license. This license allows unrestricted free usage
for both open source and commercial projects.
Enterprise Edition is commercial software built on top of the Community Edition. Enterprise is developed by the same team that
developed the OrientDB engine. It serves as an extension of the Community Edition, providing Enterprise features, such as:
Non-Stop Backup and Restore
Scheduled FULL and Incremental Backups
Query Profiler
Distributed Clustering configuration
M etrics Recording
Live M onitoring with configurable Alerts

23

Release 3.0

Release 3.0

OrientDB 3.0.0RC1 and this M anual are still in development. Not suitable for production
environments.

This Section documents what is new and what has changed in OrientDB 3.0.
What's new in OrientDB 3.0?
Available Packages
SQL Changes
API Changes
Known Issues
Upgrading to OrientDB 3.0

24

What's new in OrientDB 3.0?

OrientDB 3.0.0RC1 and this M anual are still in development. Not suitable for production
environments.

What's new in OrientDB 3.0?
New database administration, access and pooling API
OrientDB v 3.0 has a new API that is specifically intended to manipulate database instances (ie. creating and dropping databases,
checking that a DB exists, creating single db connections and connection pools).
Using this API is as simple as doing:
OrientDB orientDB = new OrientDB("embedded:/tmp/",OrientDBConfig.defaultConfig());
orientDB.create("test",ODatabaseType.PLOCAL);
try(ODatabaseDocument db = orientDB.open("test","admin","admin");) {
// Enter your code here...
}
orientDB.close();

You can also instantiate a connection pool as follows:
ODatabasePool pool = new ODatabasePool(orientDB,"test","admin","admin");
// OPEN DATABASE
try (ODatabaseDocument db = pool.acquire() {
// YOUR CODE
...
}

M ore information HERE

Graph-document concepts unification in core API
Core Graph API
In v 3.0 TinkerPop is just an alternative graph API. The main graph API provided by OrientDB is in the Core module:

25

What's new in OrientDB 3.0?

Create documents and graphs with the same API
With the ODatabaseDocument API you can now create simple documents:
OElement doc = db.newInstance("ADocumentClass");

or graphs
OVertex vertex1 = db.newVertex("AVertexClass");
OVertex vertex2 = db.newVertex("AVertexClass");
vertex1.addEdge("AnEdgeClass", vertex2);

Unified and more powerful API for properties
Now documents, vertices and edges have a single, unified API to get and set property names:
document.setProperty("name", "foo");
vertex.setProperty("name", "foo");
edge.setProperty("name", "foo");
document.getProperty("name");
vertex.getProperty("name");
edge.getProperty("name");

No more

doc.field("name")

and

vertex.getProperty("name")

!!!

Property names can now contain any character, including blank spaces, dots, brackets and special characters.
M ore information HERE

New execution plan based query engine

26

What's new in OrientDB 3.0?
OrientDB team completely re-wrote the SQL query engine. The new query engine is more strict, more accurate and explicit in the
execution planning and of course faster!
An example of the new execution planning:
SELECT sum(Amount), OrderDate
FROM Orders
WHERE OrderDate > date("2012-12-09", "yyyy-MM-dd")
GROUP BY OrderDate

+ FETCH FROM INDEX Orders.OrderDate
OrderDate > date("2012-12-09", "yyyy-MM-dd")
+ EXTRACT VALUE FROM INDEX ENTRY
+ FILTER ITEMS BY CLASS
Orders
+ CALCULATE PROJECTIONS
Amount AS _$$$OALIAS$$_1, OrderDate
+ CALCULATE AGGREGATE PROJECTIONS
sum(_$$$OALIAS$$_1) AS _$$$OALIAS$$_0, OrderDate
GROUP BY OrderDate
+ CALCULATE PROJECTIONS
_$$$OALIAS$$_0 AS `sum(Amount)`, OrderDate

You can also obtain statistics about the cost of each step in the query execution:
+ FETCH FROM INDEX Orders.OrderDate (1.445μs)
OrderDate > date("2012-12-09", "yyyy-MM-dd")
+ EXTRACT VALUE FROM INDEX ENTRY
+ FILTER ITEMS BY CLASS
Orders
+ CALCULATE PROJECTIONS (5.065μs)
Amount AS _$$$OALIAS$$_1, OrderDate
+ CALCULATE AGGREGATE PROJECTIONS (3.182μs)
sum(_$$$OALIAS$$_1) AS _$$$OALIAS$$_0, OrderDate
GROUP BY OrderDate
+ CALCULATE PROJECTIONS (1.116μs)
_$$$OALIAS$$_0 AS `sum(Amount)`, OrderDate

M ore information about SELECT execution planning, EXPLAIN, PROFILE

Support for query on remote transactions
Until V 2.2 remote connection did not allow to mix API operations and SQL statements in the same transaction. Version 3.0 finally
solves this limitation, now you can mix SQL and API operations in a single, remote transaction and the tx isolation will be guaranteed by
OrientDB, transparently.

Support streaming of query result set
In V 3.0 we re-designed the binary protocol and the ResultSet API to support streaming on query result sets. This means:
lower latency in query execution
much smaller memory footprint for query result sets, both on the server and on the client
(if you are a Java developer) a new, modern Java 8 API based on Streams to manipulate query result sets
M ore information about HERE

Integration with Apache TinkerPop 3.x
OrientDB v3.0 is compliant with TinkerPop 3.x through an external plugin.
M ore information HERE

Integration with Apache TinkerPop 2.x

27

What's new in OrientDB 3.0?
OrientDB v3.0 is backward compatible with TinkerPop 2.6.x API through an external plugin. If you built your application with
OrientDB 2.2 or minor and you don't want to migrate to the new API (the new M ulti-M odel or the new TinkerPop 3.x APIs), then
download the version with TP2 plugin included.

Externalization of object API
The Object Database API are now part of a separate module. If your existent application is using it, please include this module. For new
application we don't suggest to use the Object Database API, but rather the new M ulti-M odel API.

Improvements of storage caching for reduce latency
New Demo DB 'Social Travel Agency'
Starting with OrientDB v.3.0 a new demo database is included. M ore information on the new demo database can be found here.

28

Available Packages

OrientDB 3.0.0RC1 and this M anual are still in development. Not suitable for production
environments.

Available Packages
Starting from OrientDB 3.0, for each OrientDB Editions, different packages are available for download. Please use the package that best
fits your needs.

Community Edition
The following are the packages available for OrientDB Community Edition:
CE (orientdb-community-3.0.0RC1.tar.gz)
OrientDB Community Edition without Gremlin/TinkerPop support
CE-TP2 (orientdb-community-tp2-3.0.0RC1.tar.gz)
OrientDB Community Edition that includes support for Gremlin/TinkerPop 2.6
CE-TP3 (orientdb-community-tp3-3.0.0RC1.tar.gz)
OrientDB Community Edition that includes support for Gremlin/TinkerPop 3.x
CE-spatial-TP3 (orientdb-community-spatial-3.0.0RC1.tar.gz)
Similar to CE-TP3, i.e. OrientDB Community Edition that includes support for Gremlin/TinkerPop 3.x, but with spatial
support a sell. Warning: this package does include software that is released with LGPL license

Enterprise Edition
OrientDB Enterprise Edition is not available as 3.0 milestone preview. The Enterprise Edition will be available as soon as the GA
version of 3.0.0 is published.

29

SQL Changes

OrientDB 3.0.0RC1 and this M anual are still in development. Not suitable for production
environments.

SQL Changes
DISTINCT keyword
In v 2.2 the only way to have distinct values from a SELECT statement was using the
DISTINCT

operator, that is much more flexible than

distinct()

distinct()

function. In v 3.0 we introduced

function. The following query is valid in v 3.0

SELECT DISTINCT name, surname from Person

distinct()

function is still allowed, but it's deprecated

eval() and mathematical expressions
Until v 2.2 the only way to execute mathematical operations in SQL was to use

eval(expression)

function:

SELECT eval(' 3 + 2 ') as sum

In v 3.0 mathematical expressions are allowed in both projections and WHERE conditions, eg.
SELECT 3 + 2 as sum
SELECT FROM V WHERE theNumber > 3 + 3

Please refer to SQL syntax page for all the details

MATCH and DISTINCT
In v.2.2 the M ATCH statement automatically filters duplicate result rows and there is no way to specify a different behavior.
In v 3.0 the M ATCH by default ALLOWS duplicate results, if you want only distinct results you have to explicitly declare

RETURN

DISTINCT ...

The following statement in v.2.2
MATCH
{class:Person, as:a} -FriendOf-> {as:b}
RETURN a.name, b.name

is equivalent to v. 3.0
MATCH
{class:Person, as:a} -FriendOf-> {as:b}
RETURN DISTINCT a.name, b.name

Changes in the CREATE INDEX statement
CREATE INDEX T.id UNIQUE

is not allowed anymore, please use

30

SQL Changes
CREATE INDEX T.id ON T(id) UNIQUE

instead

Changes in the way batch script commands are separated
In v. 2.2 the newline is a valid statement separator in batch scripts. Since 3.0 the only valid statement separator is the semicolon

;

.

In v 3.0 the following script is invalid
SELECT FROM V
SELECT FROM E

The following script is valid as well
SELECT FROM V
WHERE name = 'foo';
SELECT FROM E;

Please note that the first statement is split on two rows.

EXPLAIN
BREAKING CHANGE: in v. 3.0 the EXPLAIN statement does not execute the statement anymore and does not return information
about execution statistics.
The EXPLAIN statement in v 3.0 returns details about the execution planning for the query, ie. all the steps that the query executor will
execute to calculate the query result.

Changes in the CREATE EDGE statement
Starting from 3.0, it is mandatory to create the Edge class before executing the CREATE EDGE statement. If the Edge class does not
exist the CREATE EDGE statement will fail (previously it was creating the Edge class automatically).

Changes in the DELETE EDGE statement
Starting from 3.0, it is mandatory to specify in the DELETE EDGE statement the Edge class of the edge instance you want to delete. If
the Edge class is not specified the DELETE EDGE statement will fail. So if until 2.2.x Edge class is optional and you can execute
something like
DELETE EDGE WHERE out=#9:0 AND in=#10:1

in 3.0 Edge Class is mandatory:
DELETE EDGE  WHERE out=#9:0 AND in=#10:1

To delete all edges from two specific vertices regardless of their Edge class you can simply specify the 'E' Edge Class:
DELETE EDGE E WHERE out=#9:0 AND in=#10:1

31

API Changes

OrientDB 3.0.0RC1 and this M anual are still in development. Not suitable for production
environments.

API Changes
ODatabase hierarchy and factories
TODO
OProperty
OProperty.getFullName()

now returns

"`ClassName`.`propertyName`"

instead of

"ClassName.propertyName"

OrientBaseGraph
setUseVertexFieldsForEdgeLabels(boolean)

is now deprecated and has no effect. All the edge labels are represented as edge classes.

32

Known Issues

OrientDB 3.0.0RC1 and this M anual are still in development. Not suitable for production
environments.

Known Issues
The command line tool Neo4j to OrientDB Importer tool has not been refactored using the new M ulti-M odel API. As a
consequence, if you plan to use the Neo4j to OrientDB Importer, please use it with the CE-TP2 package of OrientDB 3.0. For more
information on the available 3.0 packages, please refer to this page.

33

Upgrading to OrientDB 3.0

OrientDB 3.0.0RC1 and this M anual are still in development. Not suitable for production
environments.

Upgrading to OrientDB 3.0
General information
Developing OrientDB 3.0 we put a lot of attention on maintaining backward compatibility with v 2.2. In some cases though, we had to
do some small breaking changes to make the whole solution more consistent.
Here is a list of the things you should know when migrating to v 3.0

Schema
Case sensitive property names
In v 2.2 property names are case sensitive while working schemaless, while if you work schemaful property names are treated as case
insensitive.
Eg. consider the following queries:
Query 1:
SELECT name from V
Query 2:
SELECT Name from V

In v 2.2:
Query 1 and Query 2 are equivalent if you are working schemaless
Query 1 and Query 2 are different if you declared
In v 3.0 these two queries are always different, so

Name

name

and

property in the schema for V
name

are considered two different properties (with or without a schema)

When migrating from v 2.2 to v 3.0, review your queries and make sure that you are writing property names in the right case
Note: CLASS names are still case insensitive

Case sensitive index names
In v 2.2 index names are case insensitive
In v 3.0 index names are case sensitive
When migrating from v 2.2 to v 3.0, review your queries and make sure that you are writing index names in the right case

SQL
See full SQL reference

UPDATE ADD/PUT/INCREMENT

34

Upgrading to OrientDB 3.0
In v 2.2 there was a specific syntax for:
adding values to lists:

UPDATE AClass ADD aListProperty = "a value to add"

adding elements to maps:
incrementing values:

UPDATE AClass PUT aMapProperty = "a key to add", "a value to add"

UPDATE AClass INCREMENT aNumberProperty = 

This syntax is limitating, misleading and hard to read, so we decided to switch to a more natural syntax, as follows:

UPDATE ADD:
V 3.0 has a new

||

operator that allows to concatenate lists and sets:

UPDATE AClass ADD aListProperty = "a value to add"

becomes
UPDATE AClass SET aListProperty =

aListProperty || "a value to add"

but it can also be used to concatenate the value on the left:
UPDATE AClass SET aListProperty =

"a value to add" || aListProperty

or to concatenate multiple values:
UPDATE AClass SET aListProperty =

aListProperty || ["a value to add", "another value"]

UPDATE PUT:
The UPDATE PUT syntax is actually redundant, even in v 2.2. It can be replaced with dot notation or with square bracket notation:
UPDATE AClass PUT aMapProperty = "a key to add", "a value to add"

can be written as:
UPDATE AClass SET aMapProperty["a key to add"] = "a value to add"

or
UPDATE AClass SET aMapProperty.`a key to add` = "a value to add"

UPDATE INCREMENT
The INCREM ENT syntax is limited to adding numbers to numbers. In v 3.0 we removed this option and replaced it with a much more
flexible set of operators:
+=

// add and set

-=

// subtract and set

*=

// multiply and set

/=

// divide and set

...

The following:
UPDATE AClass INCREMENT aNumberProperty = 15

can be written as

35

Upgrading to OrientDB 3.0
UPDATE AClass SET aNumberProperty += 15

that is equivalent to
UPDATE AClass SET aNumberProperty = aNumberProperty + 15

But also the following are valid
UPDATE AClass SET aNumberProperty -= 15

equivalent to
UPDATE AClass SET aNumberProperty = aNumberProperty - 15

and so on so forth

eval() function
V 2.2 did not support expressions in SQL projections and filters, so you had to use

eval()

function to explicitly calculate them.

V 3.0 has full support for expressions in SQL, so you can re-write your queries removing the

eval()

function, eg.

SELECT eval(' age + 10 ') as ageInTenYears FROM Person

can be written as follows in v 3.0
SELECT age + 10 as ageInTenYears FROM Person

The same applies to WHERE conditions, eg. the following query is valid in v 3.0
SELECT FROM Person WHERE age + 10 < 50

FETCH PLAN
In v 3.0 FETCH PLAN is deprecated, and no longer works in most of the scenarios. It was replaced by a much more flexible syntax:
nested projections
See full syntax here

Other changes in SQL
See SQL changes

Release notes
General information on how to upgrade OrientDB can be found in the Upgrade Chapter.
You may also be interested in checking the Release Notes.

36

How to Report Bugs or Problems

Report an Issue
Very often when a new issue is open it lacks some fundamental information. This slows down the entire process because the first
question from the OrientDB team is always "What release of OrientDB are you using?" and every time a Ferret dies in the world.
So please add more information about your issue:
1. OrientDB release? (If you're using a SNAPSHOT please attach also the build number found in "build.number" file)
2. What steps will reproduce the problem? 1. 2. 3.
3. S ettings. If you're using custom settings please provide them below (to dump all the settings run the application using the JVM
argument -Denvironment.dumpCfgAtStartup=true)
4. What is the expected behavior or output? What do you get or see instead?
5. If you're describing a performance or memory problem the profiler dump can be very useful (to dump it run the application using
the JVM arguments -Dprofiler.autoDump.reset=true -Dprofiler.autoDump.interval=10 -Dprofiler.enabled=true)
Now you're ready to create a new one: https://github.com/orientechnologies/orientdb/issues/new

37

How to Get in Touch with OrientDB

How to Get in Touch with OrientDB
We want to make it super-easy for OrientDB users and contributors to talk to us and connect with each other, to share ideas, solve
problems and help make OrientDB awesome. Here are the main channels we're running currently, we'd love to hear from you on one of
them:

Google Group
OrientDB Google Group
The OrientDB Google Group (aka Community Group) is a good first stop for a general inquiry about OrientDB or a specific support
issue (e.g. trouble setting OrientDB up). It's also a good forum for discussions about the roadmap or potential new functionality.

StackOverflow
StackOverflow OrientDB tag
Feel free to ask your questions on StackOverflow under "orientdb" and "orient-db" tags.

Gitter.io
The best Web Chat, where we have an open channel. Use this is you have a question about OrientDB.

IRC
#orientdb

We're big fans of IRC here at OrientDB. We have a #orientdb channel on Freenode - stop by and say hi, you can even use Freenode's
webchat service so don't need to install anything to access it.

Twitter
@orientdb
Follow and chat to us on Twitter.

GitHub
OrientDB issues
If you spot a bug, then please raise an issue in our main GitHub project orientechnologies/orientdb. Likewise if you have developed a
cool new feature or improvement in your OrientDB fork, then send us a pull request against the "develop" branch!
If you want to brainstorm a potential new feature, then the OrientDB Google Group (see above) is probably a better place to start.

Email
info@orientdb.com
If you want more information about Commercial Support, Consultancy or Training, email us.

38

How to Contribute to OrientDB

How to Contribute to OrientDB
In order to contribute issues and pull requests, please sign OrientDB's Contributor License Agreement. The purpose of this agreement is
to protect users of this codebase by ensuring that all code is free to use under the stipulations of the Apache2 license.

Pushing into main repository
OrientDB uses different branches to support the development and release process. The

develop

branch contains code under

development for which there's not a stable release yet. When a stable version is released, a branch for the hotfix is created. Each stable
release is merged on master branch and tagged there. At the time of writing these notes, the state of branches is:
develop: work in progress for next 2.2.x release (2.2.0-SNAPSHOT)
2.1.x: hot fix for next 2.1.x stable release (2.1.10-SNAPSHOT)
2.0.x: hot fix for next 2.0.x stable release (2.0.17-SNAPSHOT)
last tag on master is 2.1.9
If you'd like to contribute to OrientDB with a patch follow the following steps:
fork the repository interested in your change. The main one is https://github.com/orientechnologies/orientdb, while some other
components reside in other projects under Orient Technologies umbrella.
clone the forked repository
select the branch, e.g the develop branch:
git checkout develop

apply your changes with your favourite editor or IDE
test that Test Suite hasn't been broken by running:
mvn clean test

if all the tests pass, then do a Pull Request (PR) against the branch (e.g.: "develop") on GitHub repository and write a comment
about the change. Please don't send PR to "master" because we use that branch only for releasing

Documentation
If you want to contribute to the OrientDB documentation, the right repository is: https://github.com/orientechnologies/orientdb-docs.
Every 24-48 hours all the contributions are reviewed and published on the public documentation.

Code formatting
You can find eclipse java formatter config file here: _base/ide/eclipse-formatter.xml.
If you use IntelliJ IDEA you can install this plugin and use formatter profile mentioned above.

Debugging
Run OrientDB as standalone server
The settings to run OrientDB Server as stand-alone (where the OrientDB's home is
community-2.2-SNAPSHOT

M ain Class:

/repositories/orientdb/releases/orientdb-

) are:

com.orientechnologies.orient.server.OServerMain

VM parameters:

-server
-DORIENTDB_HOME=/repositories/orientdb/releases/orientdb-community-2.2-SNAPSHOT
-Dorientdb.www.path=src/site
-Djava.util.logging.config.file=${ORIENTDB_HOME}/config/orientdb-server-log.properties
-Dorientdb.config.file=${ORIENTDB_HOME}/config/orientdb-server-config.xml
-Drhino.opt.level=9

39

How to Contribute to OrientDB
Use classpath of module:

orientdb-graphdb

Run OrientDB distributed
The settings to run OrientDB Server as distributed (where the OrientDB's home is
community-2.2-SNAPSHOT

M ain Class:

/repositories/orientdb/releases/orientdb-

) are:

com.orientechnologies.orient.server.OServerMain

VM parameters:

-server
-DORIENTDB_HOME=/repositories/orientdb/releases/orientdb-community-2.2-SNAPSHOT
-Dorientdb.www.path=src/site
-Djava.util.logging.config.file=${ORIENTDB_HOME}/config/orientdb-server-log.properties
-Dorientdb.config.file=${ORIENTDB_HOME}/config/orientdb-server-config.xml
-Drhino.opt.level=9
-Ddistributed=true

Use classpath of module:

orientdb-distributed

In order to debug OrientDB in distributed mode, changed the scope to "runtime" in file distributed/pom.xml:
com.orientechnologies
orientdb-graphdb
${project.version}
runtime

In this way IDE like IntelliJ can start the server correctly that requires graphdb dependency.

40

OrientDB Roadmap

OrientDB Roadmap
This page contains the roadmap with the main enhancements for the OrientDB product.

Terms
RC: Release Candidate, is a beta version with potential to be a final product, which is ready to release unless significant bugs
emerge. In this stage of product stabilization, all product features have been designed, coded and tested through one or more beta
cycles with no known showstopper-class bug. A release is called code complete when the development team agrees that no entirely
new source code will be added to this release. There could still be source code changes to fix defects, changes to documentation and
data files, and peripheral code for test cases or utilities. Beta testers, if privately selected, will often be credited for using the release
candidate as though it were a finished product. Beta testing is conducted in a client's or customer's location and to test the software
from a user's perspective.
GA: General Availability, is the stage where the software has "gone live" for usage in production. Users in production are suggested
to plan a migration for the current GA evaluating pros and cons of the upgrade.

Release 3.0
- Development started on.: June 2016
- Expected first M1......: January 2017
- Expected first M2......: February 2017
- Expected first RC......: March 2017
- Expected final GA......: March/April 2017

Status
Last update: December 14, 2016
For a more detailed an updated view, look at the Roadmap 3.0 issue.

41

OrientDB Roadmap
Module

Feature

S tatus

Core

M ulti-Threads WAL

30%

Core

WAL Compaction

30%

Core

Index rebuild avoid using WAL

0%

Core

Compression of used space on serialization

3%

Core

Improved DISKCACHE algorithm

60%

Core

Index per cluster

0%

Core

New data structure to manage edges

0%

SQL

Distributed SQL Executor

70%

SQL

M ulti-line queries in batch scripts

100%

Java API

New factories

100%

Java API

Improve SQL UPDATE syntax

100%

Java API

Support for TinkerPop 3

70%

Remote protocol

Support for server-side transactions

10%

Remote protocol

Support for server-side cursors

90%

Remote protocol

Push messages on schema change

0%

Remote protocol

Push messages on record change

0%

Distributed

Auto-Sharding

10%

Distributed

Optimized network protocol to send only the delta between updates

50%

Release 3.1
- Development started on.: - Expected first RC......: TBD
- Expected final GA......: TBD

Status
Last update: April 12, 2015
Module

Feature

S tatus

Core

Parallel Transactions

0%

Core

Indexing of embedded properties

0%

Core

Override of properties

0%

Core

Enhance isolation level also for remote commands

0%

Distributed

Optimized replication for cross Data Center

0%

Distributed

Replication of in-memory databases

0%

Lucene

Faceted search

20%

Java API

ODocument.update()

0%

SQL

shortestPaths() function

0%

SQL

New functions (strings, maths)

40%

42

OrientDB in Five M inutes

OrientDB in Five Minutes
Learn OrientDB basics in just five minutes, in your favorite programming language:
Java

43

Install

OrientDB for Java Developers in Five Minutes
If you are a Java Developer and it's the first time you approach OrientDB, then you are in the right place!
Ready? Let's start!

Step 1/5 - Download and Install
Download OrientDB from the following URL:
http://orientdb.com/download.php?file=orientdb-community-3.0.0m2.tar.gz
(you can find all the other download options here, if needed http://orientdb.com/orientdb-labs/)
Unzip it on your FileSystem and open a shell in the directory.
Now type
cd orientdb-community-3.0.0m2
cd bin

and then, if you are on Linux/OSX, you can start the server with
./server.sh

if you are on Windows, start the server with
server.bat

You will see OrientDB starting

44

Install
.`
,
`,`
.,.
.,,

`
`:.
,:`
:,,
,,,

.

.,.:::::

:::::::::

:::::::::

,`

.::,,,,::.,,,,,,`;;

`

`
.:

::::::::::

:::

`,.

::,,,,,,,:.,,.`

.:

:::

:::

:::

,,:,:,,,,,,,,::.

`

`

,,:.,,,,,,,,,: `::, ,,

`

``

.:

:::

:::

:::

::,::`

: :,::`

::::

:::

:::

:::

:::
:::
:::

,:,,,,,,,,,,::,:

,,

:.

::

:

.:

:::

:::

:::::::

:,,,,,,,,,,:,::

,,

:

:

:

:

.:

:::

:::

:::::::::

:,,,,,,,,,,:,::,

,, .::::::::

:

:

.:

:::

:::

:::

:::

:

:

.:

:::

:::

:::

:::

:::

:::

:::
:::

`

:

:::

`,...,,:,,,,,,,,,: .:,. ,, ,,
.,,,,::,,,,,,,:

`: , ,,

...,::,,,,::.. `:

.,,

,::::,,,. `:

,,

:

`

:

:

.:

:::

:,

:

:

:

.:

:::::::::::

:::

:

:

.:

:::::::::

::::::::::

:::::

,,:` `,,.
,,,
,,.
``

.,`
`,

GRAPH DATABASE

`.
``

orientdb.com

`
2017-08-14 14:11:12:824 INFO

Loading configuration from: /Users/luigidellaquila/temp/orient/orientdb-community-3.0.0m2/config

/orientdb-server-config.xml... [OServerConfigurationLoaderXml]
2017-08-14 14:11:12:932 INFO

OrientDB Server v3.0.0m2 (build 4abea780acc12595bad8cbdcc61ff96980725c3b) is starting up... [OSe

rver]
2017-08-14 14:11:12:951 INFO

OrientDB auto-config DISKCACHE=12.373MB (heap=1.963MB direct=524.288MB os=16.384MB) [orientechno

logies]
2017-08-14 14:11:12:994 INFO

Databases directory: /Users/luigidellaquila/temp/orient/orientdb-community-3.0.0m2/databases [OS

erver]
2017-08-14 14:11:13:017 INFO

Creating the system database 'OSystem' for current server [OSystemDatabase]

2017-08-14 14:11:14:457 INFO

Listening binary connections on 0.0.0.0:2424 (protocol v.37, socket=default) [OServerNetworkList

ener]
2017-08-14 14:11:14:459 INFO

Listening http connections on 0.0.0.0:2480 (protocol v.10, socket=default) [OServerNetworkListen

er]
+---------------------------------------------------------------+
|

WARNING: FIRST RUN CONFIGURATION

|

+---------------------------------------------------------------+
| This is the first time the server is running. Please type a

|

| password of your choice for the 'root' user or leave it blank |
| to auto-generate it.

|

|

|

| To avoid this message set the environment variable or JVM

|

| setting ORIENTDB_ROOT_PASSWORD to the root password to use.

|

+---------------------------------------------------------------+
Root password [BLANK=auto generate it]: *

The first time you start the server, you will be asked to enter a root password (twice). You can choose the password you prefer, just
make sure to remember it, you will need it alter.
Now you are ready for the Next Step - Create a Database >>>

45

Create a DB

OrientDB for Java Developers in Five Minutes
In the Previous Step you installed and started OrientDB on your machine, now it's time to create a database

Step 2/5 - Create a DB
Open your favourite browser (modern browser, no IE please!) and enter the following URL:
http://localhost:2480/studio/index.html
You will see this page:
Click on "NEW DB"

enter "test" as database name
enter the root password

Then click on "CREATE DATABASE"
Good job! You just created your first database!
Now, to make sure that everything is OK, try to enter the following query
SELECT * FROM OUser

and click the green "RUN" button. You should see the three default users that OrienDB creates for you: admin, reader and writer

46

Create a DB

Now you are ready for the Next Step - Create your Java Application >>>

47

Create the Java Application

OrientDB for Java Developers in Five Minutes
In the previous step you created your first database, now it's time to create a Java application that can connect to the DB, query and
manipulate it.
From now on, for this tutorial we will use IntelliJ Idea, but you can use any IDE that supports Java 8 and M aven.

Step 3/5 - Create a Maven project
Open IntelliJ Idea and:
choose the menu File -> new -> Project...

from the left menu, choose Maven
make sure that Project S DK is greater or equal to 1.8
click Next

choose your GroupId and ArtifactId (we will use "test" "test", as this is what we are doing ;-) )
click Next twice

48

Create the Java Application

Now open pom.xml file and add the following dependency:


com.orientechnologies
orientdb-client
3.0.0m2



Click on "automatically import dependencies" if needed

Now you are ready for the Next Step - Open a DB Connection and Create the DB Schema >>>

49

Connect to the DB and create the Schema

OrientDB for Java Developers in Five Minutes
In the previous step you created your Java application scaffolding in IntelliJ Idea, now it's time to create a Java class that connects to
the database and does basic operations
We will write a very simple application with two classes:
Person: a vertex type containing information about people
FriendOf: an edge class that connects people together

Step 4/5 - Connect to the DB and create a basic schema
Let's create a simple Java class
Open the folder src -> main -> java
Right-click on the java folder and choose New -> Java Class

Give the class the name you prefer and click OK
create a main method

Connecting to the DB
Now it's time to connect to OrientDB
Create an OrientDB object to manage the remote server
Also invoke a

close()

at the end of the method (so that you don't forget it later)

OrientDB orient = new OrientDB("remote:localhost", OrientDBConfig.defaultConfig());
//let's do something with this server!
orient.close();

The first argument of
remote

OrientDB()

constructor is the URL of the remote database. It's made of two parts:

: specifies that we are connecting to a remote (stand-alone) server

localhost

: the address of the host where OrientDB is running (it can be a URL or an IP, in this case orientdb is running on the

local machine)

50

Connect to the DB and create the Schema
Until now, we just established a connection with the server, but not with the database itself (we created a db named test, do you
remember?).
Now it's time to open a database session (and remember to close it at the end!):
OrientDB orient = new OrientDB("remote:localhost", OrientDBConfig.defaultConfig());
ODatabaseSession db = orient.open("test", "admin", "admin");
//let's do something with this session!
db.close();
orient.close();

Here we are actually connecting to the database. The three parameters are:
test

: the database name (we created it a couple of steps before)

admin

(the first one): the username used to connect

admin

(the second one): the password for the connection

By default, when you create a new database, OrientDB creates three users for you:
users are the same as the user names, eg. the password for

admin

is

admin

admin

,

reader

,

writer

; the passwords for these

. You can change it later of course, and you can define more

users if needed.

Creating the schema
Now it's time to create a schema for our db. Do you remember? We are creating a graph of people who are friends, so we need a
vertex class and a

FriendOf

Person

edge class.

Let's also add a little check to make sure that the classes do not already exist
if (db.getClass("Person") != null) {
db.createVertexClass("Person");
}
if (db.getClass("FriendOf") != null) {
db.createEdgeClass("FriendOf");
}

And this is the final version of our class

This is the full source code:

51

Connect to the DB and create the Schema
import com.orientechnologies.orient.core.db.ODatabaseSession;
import com.orientechnologies.orient.core.db.OrientDB;
import com.orientechnologies.orient.core.db.OrientDBConfig;
public class Main {
public static void main(String[] args) {
OrientDB orient = new OrientDB("remote:localhost", OrientDBConfig.defaultConfig());
ODatabaseSession db = orient.open("test", "admin", "admin");
if (db.getClass("Person") == null) {
db.createVertexClass("Person");
}
if (db.getClass("FriendOf") == null) {
db.createEdgeClass("FriendOf");
}
db.close();
orient.close();
}
}

Now just run it and then open OrientDB Studio again:
go back to the browser (OrientDB Studio)
click on the S CHEMA tab
you will see the two newly created classes:

Person

and

FriendOf

Just to make it a bit more realistic, let's also create some basic schema for our
We will just add a

name

Person

class.

to the Person and we will create an index on it.

52

Connect to the DB and create the Schema
OClass person = db.getClass("Person");
if (person == null) {
person = db.createVertexClass("Person");
}
if (person.getProperty("name") == null) {
person.createProperty("name", OType.STRING);
//

index name

index type

property name

person.createIndex("Person_name_index", OClass.INDEX_TYPE.NOTUNIQUE, "name");
}

And this is the final result:
import com.orientechnologies.orient.core.db.ODatabaseSession;
import com.orientechnologies.orient.core.db.OrientDB;
import com.orientechnologies.orient.core.db.OrientDBConfig;
import com.orientechnologies.orient.core.metadata.schema.OClass;
import com.orientechnologies.orient.core.metadata.schema.OType;
public class Main {
public static void main(String[] args) {
OrientDB orient = new OrientDB("remote:localhost", OrientDBConfig.defaultConfig());
ODatabaseSession db = orient.open("test", "admin", "admin");
OClass person = db.getClass("Person");
if (person == null) {
person = db.createVertexClass("Person");
}
if (person.getProperty("name") == null) {
person.createProperty("name", OType.STRING);
person.createIndex("Person_name_index", OClass.INDEX_TYPE.NOTUNIQUE, "name");
}
if (db.getClass("FriendOf") == null) {
db.createEdgeClass("FriendOf");
}
db.close();
orient.close();
}
}

Now you are ready for the Next Step - Create your First Graph and Run Queries >>>

53

Create your First Graph and Run Queries

OrientDB for Java Developers in Five Minutes
In the previous step you established a DB connection from Java, then you created the DB schema (two classes and an index)
Now it's time to insert and query some data

Step 5/5 - Create and Query a Graph
First of all, let's create three vertices: Alice, Bob and Jim

Creating vertices
We are good Java developers, aren't we? Let's encaplusate a single vertex creation in a method:
private static OVertex createPerson(ODatabaseSession db, String name, String surname) {
OVertex result = db.newVertex("Person");
result.setProperty("name", name);
result.setProperty("surname", surname);
result.save();
return result;
}

Wow, we never mentioned that people have a

surname

!!! In the previous section we just defined the schema for

name

property...

OrientDB can work schemaful (with all the property names and types defined), schemaless (schema-free, no schema defined) or
schema-mixed like in this case, where we define a part of the schema (ie. the

name

) but we leave the developer the ability to add new

properties at run time, without having to deal with further schema definitions.
Now let's create the three vertices:
private static void createPeople(ODatabaseSession db){
OVertex alice = createPerson(db, "Alice", "Foo");
OVertex bob = createPerson(db, "Bob", "Bar");
OVertex jim = createPerson(db, "Jim", "Baz");
}

Creating edges
Suppose that Alice is a friend of Bob and that Bob is a friend of Jim:
Alice --FriendOf--> Bob --FriendOf--> Jim

Let's create the edges in the database:
OEdge edge1 = alice.addEdge(bob, "FriendOf");
OEdge edge2 = bob.addEdge(jim, "FriendOf");

Please cosider that edges are plain documents, so you can get/set properties on them exactly like for vertices.

Executing queries
Last step of this journey: let's write and execute a simple query that finds friends of friends (FoaF) of a person. We will use a SELECT
for this.

54

Create your First Graph and Run Queries
private static void executeAQuery(ODatabaseSession db) {
String query = "SELECT expand(out('FriendOf').out('FriendOf')) from Person where name = ?";
OResultSet rs = db.query(query, "Alice");
while (rs.hasNext()) {
OResult item = rs.next();
System.out.println("friend: " + item.getProperty("name"));
}
rs.close(); //REMEMBER TO ALWAYS CLOSE THE RESULT SET!!!
}

or, if you prefer Java Streams API:
private static void executeAQuery(ODatabaseSession db) {
String query = "SELECT expand(out('FriendOf').out('FriendOf')) from Person where name = ?";
OResultSet rs = db.query(query, "Alice");
rs.stream().forEach(x -> System.out.println("friend: " + x.getProperty("name")));
rs.close();
}

Let's try a more complex query, let's find all the people that are friends of both Alice and Jim. We will use a M ATCH for this.
private static void executeAnotherQuery(ODatabaseSession db) {
String query =
" MATCH

" +

"

{class:Person, as:a, where: (name = :name1)}, " +

"

{class:Person, as:b, where: (name = :name2)}, " +

"

{as:a} -FriendOf-> {as:x} -FriendOf-> {as:b}

" RETURN x.name as friend

" +
";

Map params = new HashMap();
params.put("name1", "Alice");
params.put("name2", "Jim");
OResultSet rs = db.query(query, params);
while (rs.hasNext()) {
OResult item = rs.next();
System.out.println("friend: " + item.getProperty("name"));
}
rs.close();
}

Good job!!! This is your first OrientDB Java program!
Here is the full source code of the main class:
import com.orientechnologies.orient.core.db.ODatabaseSession;
import com.orientechnologies.orient.core.db.OrientDB;
import com.orientechnologies.orient.core.db.OrientDBConfig;
import com.orientechnologies.orient.core.metadata.schema.OClass;
import com.orientechnologies.orient.core.metadata.schema.OType;
import com.orientechnologies.orient.core.record.OEdge;
import com.orientechnologies.orient.core.record.OVertex;
import com.orientechnologies.orient.core.sql.executor.OResult;
import com.orientechnologies.orient.core.sql.executor.OResultSet;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
OrientDB orient = new OrientDB("remote:localhost", OrientDBConfig.defaultConfig());
ODatabaseSession db = orient.open("test", "admin", "admin");
createSchema(db);

55

Create your First Graph and Run Queries

createPeople(db);
executeAQuery(db);
executeAnotherQuery(db);
db.close();
orient.close();
}
private static void createSchema(ODatabaseSession db) {
OClass person = db.getClass("Person");
if (person == null) {
person = db.createVertexClass("Person");
}
if (person.getProperty("name") == null) {
person.createProperty("name", OType.STRING);
person.createIndex("Person_name_index", OClass.INDEX_TYPE.NOTUNIQUE, "name");
}
if (db.getClass("FriendOf") == null) {
db.createEdgeClass("FriendOf");
}
}
private static void createPeople(ODatabaseSession db) {
OVertex alice = createPerson(db, "Alice", "Foo");
OVertex bob = createPerson(db, "Bob", "Bar");
OVertex jim = createPerson(db, "Jim", "Baz");
OEdge edge1 = alice.addEdge(bob, "FriendOf");
OEdge edge2 = bob.addEdge(jim, "FriendOf");
}
private static OVertex createPerson(ODatabaseSession db, String name, String surname) {
OVertex result = db.newVertex("Person");
result.setProperty("name", name);
result.setProperty("surname", surname);
result.save();
return result;
}
private static void executeAQuery(ODatabaseSession db) {
String query = "SELECT expand(out('FriendOf').out('FriendOf')) from Person where name = ?";
OResultSet rs = db.query(query, "Alice");
while (rs.hasNext()) {
OResult item = rs.next();
System.out.println("friend: " + item.getProperty("name"));
}
rs.close(); //REMEMBER TO ALWAYS CLOSE THE RESULT SET!!!
}
private static void executeAnotherQuery(ODatabaseSession db) {
String query =
" MATCH

" +

"

{class:Person, as:a, where: (name = :name1)}, " +

"

{class:Person, as:b, where: (name = :name2)}, " +

"

{as:a} -FriendOf-> {as:x} -FriendOf-> {as:b}

" RETURN x.name as friend

" +
";

Map params = new HashMap();
params.put("name1", "Alice");
params.put("name2", "Jim");
OResultSet rs = db.query(query, params);
while (rs.hasNext()) {
OResult item = rs.next();
System.out.println("friend: " + item.getProperty("name"));

56

Create your First Graph and Run Queries
}
rs.close();
}
}

Next steps:
You may be interested in:
M ore details about the Java M ulti-M odel API
Full SQL Syntax

57

Getting Started

Getting Started

58

Installation

Installation
OrientDB Community Edition is available as a binary package for download or as source code on GitHub. The Enterprise Edition is
available as a binary package to all our Customers that purchased one of the available Subscriptions. A 45-days Enterprise Edition trial
for development purposes is available as well.
OrientDB prerequisites can be found here.

Use Docker
If you have Docker installed in your computer, this is the easiest way to run OrientDB. From the command line type:
$ docker run -d --name orientdb -p 2424:2424 -p 2480:2480
-e ORIENTDB_ROOT_PASSWORD=root orientdb:latest

Where instead of "root", type the root's password you want to use.

Use Ansible
If you manage your servers through Ansible, you can use the following role : https://galaxy.ansible.com/migibert/orientdb which is highly
customizable and allows you to deploy OrientDB as a standalone instance or multiple clusterized instances.
For using it, you can follow these steps :
Install the role
ansible-galaxy install migibert.orientdb

Create an Ansible inventory
Assuming you have one two servers with respective IPs fixed at 192.168.10.5 and 192.168.10.6, using ubuntu user.
[orientdb-servers]
192.168.20.5 ansible_ssh_user=ubuntu
192.168.20.6 ansible_ssh_user=ubuntu

Create an Ansible playbook
In this example, we provision a two node cluster using multicast discovery mode. Please note that this playbook assumes java is already
installed on the machine so you should have one step before that install Java 8 on the servers

59

Installation
- hosts: orientdb-servers
become: yes
vars:
orientdb_version: 2.0.5
orientdb_enable_distributed: true
orientdb_distributed:
hazelcast_network_port: 2434
hazelcast_group: orientdb
hazelcast_password: orientdb
multicast_enabled: True
multicast_group: 235.1.1.1
multicast_port: 2434
tcp_enabled: False
tcp_members: []
orientdb_users:
- name: root
password: root
tasks:
- apt:
name: openjdk-8-jdk
state: present
roles:
- role: orientdb-role

Run the playbook

ansible-playbook -i inventory playbook.yml

Binary Installation
OrientDB provides a pre-compiled binary package to install the database on your system. Depending on your operating system, this is
a tarred or zipped package that contains all the relevant files you need to run OrientDB. For desktop installations, go to OrientDB
Downloads and select the package that best suits your system.
On server installations, you can use the

utility:

wget

$ wget http://orientdb.com/download.php?file=orientdb-community-importers-3.0.0RC1.tar.gz&utm_source=Labs&utm_medium=link&utm_
campaign=300 -O orientdb-community-3.0.0RC1.tar.gz

Whether you use your web browser or
example,

/opt/orientdb/

wget

, unzip or extract the downloaded file into a directory convenient for your use, (for

on Linux). This creates a directory called orientdb-community-3.0.0RC1 with relevant files and scripts,

which you will need to run OrientDB on your system.

Source Code Installation
For information on how to install OrientDB from source, please refer to this Section.

Post-installation Tasks
For desktop users installing the binary, OrientDB is now installed and can be run through shell scripts found in the package

bin

directory of the installation. For servers, there are some additional steps that you need to take in order to manage the database server for
OrientDB as a service. The procedure for this varies, depending on your operating system.
Install as Service on Unix, Linux and M ac OS X
Install as Service on M icrosoft Windows

Upgrading
When the time comes to upgrade to a newer version of OrientDB, the methods vary depending on how you chose to install it in the first
place. If you installed from binary downloads, repeat the download process above and update any symbolic links or shortcuts to point
to the new directory.

60

Installation
For systems where OrientDB was built from source, pull down the latest source code and compile from source.
$ git pull origin master
$ mvn clean install

Bear in mind that when you build from source, you can switch branches to build different versions of OrientDB using Git. For example,
$ git checkout 2.2.x
$ mvn clean install

builds the

2.2.x

branch, instead of

master

.

Building a single executable jar with OrientDB
OrientDB for internal components like engines, operators, factories uses Java SPI Service Provider Interface. That means that the jars of
OrientDB are shipped with files in

META-INF/services

that contains the implementation of components. Bear in mind that when

building a single executable jar, you have to concatenate the content of files with the same name in different orientdb-*.jar . If you are
using M aven Shade Plugin you can use Service Resource Transformer to do that.

Other Resources
To learn more about how to install OrientDB on specific environments, please refer to the guides below:
Install with Docker
Install with Ansible
Install on Linux Ubuntu
Install on JBoss AS
Install on GlassFish
Install on Ubuntu 12.04 VPS (DigitalOcean)
Install on Vagrant

61

Run the server

Running the OrientDB Server
When you finish installing OrientDB, whether you build it from source or download the binary package, you are ready to launch the
database server. You can either start it through the system daemon or through the provided server script. This article only covers the
latter.
Note: If you would like to run OrientDB as a service on your system, there are some additional steps that you need to take. This
provides alternate methods for starting the server and allows you to launch it as a daemon when your system boots. For more
information on this process see:
Install OrientDB as a Service on Unix, Linux and M ac OS X
Install OrientDB as a Service on M icrosoft Windows

Starting the Database Server
While you can run the database server as system daemon, you also have the option of starting it directly. In the OrientDB installation
directory, (that is

$ORIENTDB_HOME

), under

bin

, there is a file named

server.sh

on Unix-based systems and

server.bat

on

Windows. Executing this file starts the server.
To launch the OrientDB database server, run the following commands:

62

Run the server

$

cd $ORIENTDB_HOME/bin

$

./server.sh

.
.`
,

`
`:.

`,`
.,.
.,,

,:`
:,,
,,,

.

.,.:::::

,`

.::,,,,::.,,,,,,`;;

````

`,.

::,,,,,,,:.,,.`

,,:,:,,,,,,,,::.

`

.:

`

`

,,:.,,,,,,,,,: `::, ,,

`

.:
``

::,::`

,:,,,,,,,,,,::,:

,,

:.

:,,,,,,,,,,:,::

,,

:

:,,,,,,,,,,:,::,

:

: :,::`

::::

::

:

.:

:

:

:

.:

,, .::::::::

:

:

.:

:

:

.:

`,...,,:,,,,,,,,,: .:,. ,, ,,
.,,,,::,,,,,,,:

.:

`: , ,,

...,::,,,,::.. `:

.,,

,::::,,,. `:

,,

:

`

:

:

.:

:,

:

:

:

.:

:

:

.:

:::::

,,:` `,,.
,,,
,,.
``

.,`
`,

S E R V E R

`.
``
`

2012-12-28 01:25:46:319 INFO Loading configuration from: config/orientdb-serverconfig.xml... [OServerConfigurationLoaderXml]
2012-12-28 01:25:46:625 INFO OrientDB Server v1.6 is starting up... [OServer]
2012-12-28 01:25:47:142 INFO -> Loaded memory database 'temp' [OServer]
2012-12-28 01:25:47:289 INFO Listening binary connections on 0.0.0.0:2424
[OServerNetworkListener]
2012-12-28 01:25:47:290 INFO Listening http connections on 0.0.0.0:2480
[OServerNetworkListener]
2012-12-28 01:25:47:317 INFO OrientDB Server v1.6 is active. [OServer]

The database server is now running. It is accessible on your system through ports

2424

and

2480

. At the first startup the server will

ask for the root user password. The password is stored in the config file.

Stop the Server
On the console where the server is running a simple CTRL+c will shutdown the server.
The shutdown.sh (shutdown.bat) script could be used to stop the server:
$

cd $ORIENTDB_HOME/bin

$

./shutdown.sh -p ROOT_PASSWORD

On *nix systems a simple call to shutdown.sh will stop the server running on localhost:
$

cd $ORIENTDB_HOME/bin

$

./shutdown.sh

63

Run the server
It is possible to stop servers running on remote hosts or even on different ports on localhost:
$

cd $ORIENTDB_HOME/bin

$

./shutdown.sh -h odb1.mydomain.com -P 2424-2430 -u root -p ROOT_PASSWORD

List of params
-h | --host HOS TNAME or IP ADDRES S : the host or ip where OrientDB is running, default to localhost
-P | --ports PORT or PORT RANGE : single port value or range of ports; default to 2424-2430
-u | --user ROOT US ERNAME : root's username; deafult to root
-p | --password ROOT PAS S WORD : root's user password; mandatory
NOTE: On Windows systems password is always mandatory because the script isn't able to discover the pid of the OrientDB's
process.

Server Log Messages
Following the masthead, the database server begins to print log messages to standard output. This provides you with a guide to what
OrientDB does as it starts up on your system.
1. The database server loads its configuration file from the file

$ORIENTDB_HOME/config/orientdb-server-config.xml

.

For more information on this step, see OrientDB Server.
2. The database server loads the

temp

database into memory. You can use this database for storing temporary data.

3. The database server begins listening for binary connections on port

2424

for all configured networks, (

0.0.0.0

).

4. The database server begins listening for HTTP connections on port

2480

for all configured networks, (

0.0.0.0

).

Accessing the Database Server
By default, OrientDB listens on two different ports for external connections.
Binary: OrientDB listens on port

2424

for binary connections from the console and for clients and drivers that support the

Network Binary Protocol.
HTTP: OrientDB listens on port

2480

for HTTP connections from OrientDB Studio Web Tool and clients and drivers that

support the HTTP/REST protocol, or similar tools, such as cURL.
If you would like the database server to listen at different ports or IP address, you can define these values in the configuration file
config/orientdb-server-config.xml

.

64

Run the console

Running the OrientDB Console
Once the server is running there are various methods you can use to connect to your database server to an individual databases. Two
such methods are the Network Binary and HTTP/REST protocols. In addition to these OrientDB provides a command-line interface for
connecting to and working with the database server.

Starting the OrientDB Console
In the OrientDB installation directory (that is,
console.sh

for Unix-based systems or

$ORIENTDB_HOME

console.bat

, where you installed the database) under

bin

, there is a file called

for Windows users.

To launch the OrientDB console, run the following command after you start the database server:
$

cd $ORIENTDB_HOME/bin

$

./console.sh

OrientDB console v.X.X.X (build 0) www.orientdb.com
Type 'HELP' to display all the commands supported.
Installing extensions for GREMLIN language v.X.X.X
orientdb>

The OrientDB console is now running. From this prompt you can connect to and manage any remote or local databases available to you.

Using the

HELP

Command

In the event that you are unfamiliar with OrientDB and the available commands, or if you need help at any time, you can use the
command, or type
orientdb>

?

HELP

into the console prompt.

HELP

AVAILABLE COMMANDS:
* alter class 

Alter a class in the database schema

* alter cluster  Alter class in the database schema
...

...

* help

Print this help

* exit

Close the console

For each console command available to you,

HELP

documents its basic use and what it does. If you know the particular command and

need details on its use, you can provide arguments to
orientdb>

HELP

for further clarification.

HELP SELECT

COMMAND: SELECT
- Execute a query against the database and display the results.
SYNTAX: select 
WHERE:
- : The query to execute

65

Run the console

Connecting to Server Instances
There are some console commands, such as

LIST DATABASES

or

CREATE DATABASE

, which you can only run while connected to a server

instance. For other commands, however, you must also connect to a database, before they run without error.
Before you can connect to a fresh server instance and fully control it, you need to know the root password for the database. The
root password is located in the configuration file at

config/orientdb-server-config.xml

. You can find it by searching for the

element. If you want to change it, edit the configuration file and restart the server.



...




...

With the required credentials, you can connect to the database server instance on your system, or establish a remote connection to one
running on a different machine.
orientdb>

CONNECT remote:localhost root my_root_password

Connecting to remote Server instance [remote:localhost] with user 'root'...OK

Once you have established a connection to the database server, you can begin to execute commands on that server, such as
DATABASES

and

orientdb>

CREATE DATABASE

LIST

.

LIST DATABASES

Found 1 databases:
* GratefulDeadConcerts (plocal)

To connect to this database or to a different one, use the
and password. By default, each database has an

admin

CONNECT

command from the console and specify the server URL, username,

user with a password of

admin

.

Warning: Always change the default password on production databases.
The above

LIST DATABASES

command shows a

GratefulDeadConcerts

installed on the local server. To connect to this database, run the

following command:
orientdb>

CONNECT remote:localhost/GratefulDeadConcerts admin admin

Connecting to database [remote:localhost/GratefulDeadConcerts] with user 'admin'...OK

The

CONNECT

command takes a specific syntax for its URL. That is,

remote:localhost/GratefulDeadConcerts

in the example. It has

three parts:
Protocol: The first part of the database address is the protocol the console should use in the connection. In the example, this is
remote

, indicating that it should use the TCP/IP protocol.

Address: The second part of the database address is hostname or IP address of the database server that you want the console to
connect to. In the example, this is

localhost

, since the connection is made to a server instance running on the local file system.

Database: The third part of the address is the name of the database that you want to use. In the case of the example, this is
GratefulDeadConcerts

.

66

Run the console
For more detailed information about the commands, see Console Commands.
Note: The OrientDB distribution comes with the bundled database

GratefulDeadConcerts

which represents the Graph of the

Grateful Dead's concerts. This database can be used by anyone to start exploring the features and characteristics of OrientDB.

67

Run the Studio

Run the Studio
If you're more comfortable interacting with database systems through a graphical interface then you can accomplish the most common
database tasks with OrientDB Studio, the web interface.

Connecting to Studio
By default, there are no additional steps that you need to take to start OrientDB Studio. When you launch the Server, whether through
the start-up script
$

server.sh

or as a system daemon, the Studio web interface opens automatically with it.

firefox http://localhost:2480

68

Run the Studio

From here you can create a new database, connect to or drop an existing database, import a public database and navigate to the Server
management interface.
For more information on the OrientDB Studio, see Studio.

69

Documents, Vertices and Edges

Documents, Vertices and Edges
TODO

70

Classes, Schema and Constraints

Classes
Here we will learn about how classes structure data in OrientDB. A class in OrientDB is similar to a table in a relational database with
some key differences. In this section you will learn how to see all of the classes in your database and how to create classes of your own.
You'll also learn how to provide schema on top of classes by defining constraints for a class's properties. Finally you'll learn how to
access the records stored within your classes.
The Class is a concept drawn from the Object-oriented programming paradigm. In OrientDB a class is a data model that allows you to
define certain rules for records that belong together. For example, a class 'Person' can store information about people. You can structure
your class such that a record in the class must have certain properties (i.e. Name, Birthdate, Favorite Number, etc...).

In the traditional document database model classes are comparable to collections, while in the Relational database model (R-DBM S)
they are comparable to tables. Classes are not tables though. Classes provide efficient means for storage of schema-less data. We'll see
more about schema-less, schema-full, and schema-mixed data models later (See 'Adding Properties to a Class' below).
Like many database management systems, OrientDB uses the Record as an element of storage. There are many types of records, but
with the Document Database API records always use the Document type. A document is formed by a set of key/value pairs. A
document can belong to a class.
In the example above, there are two documents. One document contains information for Sarah and another for Abdul. The keys 15:0 and
15:1 refer to each document respectively.
To list all the configured classes on your system, use the

LIST CLASSES

command in the console:

71

Classes, Schema and Constraints

orientdb>

LIST CLASSES

orientdb {db=playingwithClasses}> LIST CLASSES
CLASSES
+----+-----------+-------------+-----------------+-----+
|#

|NAME

|SUPER-CLASSES|CLUSTERS

|COUNT|

+----+-----------+-------------+-----------------+-----+
|0

|_studio

|

|_studio(13)

|

1|

|1

|Blue

|[Color]

|blue(19)

|

0|

|2

|Color

|[V]

|-

|

0|

|3

|E

|

|e(11),e_1(12)

|

0|

|4

|OFunction

|

|ofunction(6)

|

0|

|5

|OIdentity

|

|-

|

0|

|6

|ORestricted|

|-

|

0|

|7

|ORole

|[OIdentity]

|orole(4)

|

3|

|8

|OSchedule

|

|oschedule(8)

|

0|

|9

|OSequence

|

|osequence(7)

|

0|

|10

|OTriggered |

|-

|

0|

|11

|OUser

|[OIdentity]

|ouser(5)

|

3|

|12

|Person

|[V]

|person(15)

|

0|

|13

|Red

|[Color]

|red(17),red_1(18)|

0|

|14

|V

|

|v(9),v_1(10)

0|

|

+----+-----------+-------------+-----------------+-----+
|

|TOTAL

|

|

|

7|

+----+-----------+-------------+-----------------+-----+

If you are using studio, then you can see the same information by clicking on the 'schema' tab.
Here we can see that there are 14 classes in the database. Class 12 refers to person. There is also a class Color which is the super-class
of Red and Blue. Color and Person both have super-classes called V. The class V is important for using OrientDB’s graph model. We'll
see more about Superclasses and V later in the tutorial. Let's move on now to working with classes.

Working with Classes
In order to start using classes with your own applications, you need to understand how to create and configure a class for use. The class
in OrientDB is similar to the table in relational databases, but unlike tables, classes can be schema-less, schema-full or mixed. A class can
inherit properties from other classes thereby creating trees of classes (though the super-class relationship).
Each class has its own cluster or clusters, (created by default, if none are defined). For now we should know that a cluster is a place
where a group of records are stored. We'll soon see how

clustering

improves performance of querying the database.

For more information on classes in OrientDB, see Class.
To create a new class, use the
orientdb>

CREATE CLASS

command:

CREATE CLASS Student

Class created successfully. Total classes in database now: 15

This creates a class called
cluster called

student

now displayed in the

Student

. Given that no cluster was defined in the

CREATE CLASS

command, OrientDB creates a default

, to contain records assigned to this class. For the moment, the class has no records or properties tied to it. It is
CLASSES

listing and in the schema manager of Studio.

Adding Properties to a Class

72

Classes, Schema and Constraints
As mentioned above, OrientDB allows you to work in a schema-less mode. That is, it allows you to create classes without defining their
properties. However, properties are mandatory if you would like to define indexes or constraints for a class. Let's follow OrientDB's
comparison to relational databases again... If classes in OrientDB are similar to tables, then properties are the columns on those tables.
To create new properties on
orientdb>

Student

, use the

CREATE PROPERTY

command in the console or in the browse window of studio:

CREATE PROPERTY Student.name STRING

Property created successfully with id=1

orientdb>

CREATE PROPERTY Student.surname STRING

Property created successfully with id=2

orientdb>

CREATE PROPERTY Student.birthDate DATE

Property created successfully with id=3

These commands create three new properties on the

Student

class. The properties provide you with areas to define an individual

student's name, surname, and date of birth.

Displaying Class Information
Occasionally you may need to reference a particular class to see what clusters it belongs to, or any properties configured for the class's
use. Use the

INFO CLASS

command to display information about the current configuration and properties of a class.

To display information on the class
orientdb>

Student

, use the

INFO CLASS

command:

INFO CLASS Student

Class................: Student
Default cluster......: student (id=96)
Supported cluster ids: [96]
Properties:
-----------+--------+--------------+-----------+----------+----------+-----+-----+
NAME

| TYPE

| LINKED TYPE/ | MANDATORY | READONLY | NOT NULL | MIN | MAX |

|

| CLASS

|

|

|

|

|

|

-----------+--------+--------------+-----------+----------+----------+-----+-----+
birthDate | DATE

| null

| false

| false

| false

|

|

|

name

| STRING | null

| false

| false

| false

|

|

|

surname

| STRING | null

| false

| false

| false

|

|

|

-----------+--------+--------------+-----------+----------+----------+-----+-----+

Adding Constraints to Properties
Constraints create limits on the data values assigned to properties. For instance, the type, the minimum or maximum size of, whether or
not a value is mandatory or if null values are permitted to the property.
Constraints create limits on the data values assigned to properties. For instance, if 'M ANDATORY' is set to true for name in student,
then every record in the student class must have a name. If we set 'M IN' to three, then every name must also be at least three characters
long.
The only two properties required when using the 'create a property' command for a class are 'NAM E' and 'TYPE'.
To add a constraint to an existing property, use the

ALTER PROPERTY

command:

73

Classes, Schema and Constraints

orientdb>

ALTER PROPERTY Student.name MIN 3

Property updated successfully

This command adds a constraint to

Student

on the

name

property. After running this command, Student will allow any record to be

stored unless the record has a property called 'Name'. If the records has such a property then 'Student' will reject the record if the value
in 'Name' is less then three characters.
By setting property, 'M ANDATORY', to true for Student's Name we can also guarantee that every record added to student has a name.
orientdb>

ALTER PROPERTY Student.name MANDATORY true

There are many ways to use constraints on properties. They can allow you to build a data-model that tells a story about your own use
case. Constraints can also help ensure that you're database communicates with other components of a larger application by only
allowing storage of values that another application is able to recognize.

Viewing Records in a Class
Classes contain and define records in OrientDB. You can view all records that belong to a class using the
can also see data belonging to a particular record with the

DISPLAY RECORD

BROWSE CLASS

command. You

command.

Note: you cannot display a record unless you have recently received a query result with records to browse (select statement,
'browse class x', etc...).
Earlier we created a

Student

class and defined some schema for records belonging to that class, but we didn't create any records or add

any data. Thus, running 'BROWSE CLASS' on the

Student

class returns no results. Luckily OrientDB has a few preconfigured classes

and records that we can query.
Let's take the class OUser for example.

74

Classes, Schema and Constraints

orientdb>

INFO CLASS OUser

CLASS 'OUser'
Super classes........: [OIdentity]
Default cluster......: ouser (id=5)
Supported cluster ids: [5]
Cluster selection....: round-robin
Oversize.............: 0.0
PROPERTIES
----------+---------+--------------+-----------+----------+----------+-----+-----+
NAME

| TYPE

| LINKED TYPE/ | MANDATORY | READONLY | NOT NULL | MIN | MAX |

|

| CLASS

|

|

|

|

|

|

----------+---------+--------------+-----------+----------+----------+-----+-----+
password | STRING

| true

| false

| true

|

|

|

roles

| LINKSET | ORole

| null

| false

| false

| false

|

|

|

name

| STRING

| null

| true

| false

| true

|

|

|

status

| STRING

| null

| true

| false

| true

|

|

|

----------+---------+--------------+-----------+----------+----------+-----+-----+
INDEXES (1 altogether)
-------------------------------+----------------+
NAME

| PROPERTIES

|

-------------------------------+----------------+
OUser.name

| name

|

-------------------------------+----------------+

The

OUser

class defines the users on your database.

To see records assigned to the
orientdb>

OUser

class, run the

BROWSE CLASS

command:

BROWSE CLASS OUser

---+------+-------+--------+-----------------------------------+--------+-------+
# | @RID | @Class| name

| password

| status | roles |

---+------+-------+--------+-----------------------------------+--------+-------+
0 | #5:0 | OUser | admin

| {SHA-256}8C6976E5B5410415BDE90... | ACTIVE | [1]

|

1 | #5:1 | OUser | reader | {SHA-256}3D0941964AA3EBDCB00EF... | ACTIVE | [1]

|

2 | #5:2 | OUser | writer | {SHA-256}B93006774CBDD4B299389... | ACTIVE | [1]

|

---+------+-------+--------+-----------------------------------+--------+-------+

In the example, you are listing all of the users of the database. While this is fine for your initial setup and as an
example, it is not particularly secure. To further improve security in production environments, see Security.

When you run

BROWSE CLASS

, the first column in the output provides the identifier number, which you can use to display detailed

information on that particular record.
To show the first record browsed from the

OUser

class, run the

DISPLAY RECORD

command:

75

Classes, Schema and Constraints

orientdb>

DISPLAY RECORD 0

DOCUMENT @class:OUser @rid:#5:0 @version:1
----------+--------------------------------------------+
Name | Value

|

----------+--------------------------------------------+
name | admin

|

password | {SHA-256}8C6976E5B5410415BDE908BD4DEE15... |
status | ACTIVE

|

roles | [#4:0=#4:0]

|

----------+--------------------------------------------+

Bear in mind that this command references the last call of

BROWSE CLASS

. You can continue to display other records, but you cannot

display records from another class until you browse that particular class.

Class Review
Here are some key things to remember about classes:
1) A class in OrientDB is similar to a table in a relational database with some key differences. Among those differences we see tables are
schema-full, and classes can be schema-full, schema-less, or mixed.
2) You can see all of the classes in your database by running 'LIST CLASSES' in console or by visiting the 'Schema M anager' in Studio.
3) You can create a class by running the 'create class ' command in console, or by running the same command in the 'Browse' window of
studio.
4) You can use the commands, 'Create property [constraints]' and 'Create property [constraints]' to give schema to a class.
5) To see properties and constraints associated with a class you can run 'info class '.
6) To see information about a the records within a class run 'Browse class '.
7) To see information about a specific record of a class use the command 'Display record '. Note: You must have recently queried a class
for it's records before using this command. '' references the number in the left-most column of the previous query's result.
Congratulations! You are now familiar with classes in OrientDB. If you're ready to explore clusters then let's move on to the
clustering

section of this tutorial.

76

Demo Database

Demo Database
Starting with OrientDB v.3.0 a new demo database (
This Section introduces the

demodb

demodb

) is included.

database and its Data M odel, and includes some queries that is possible to execute on it.

Some screenshots on "portions" of the

demodb

graph are included as well.

77

Introduction

Introduction
The demo database can help you understand better OrientDB features and capabilities and replaces the old demo database
included in version 2.2 and previous ones.

GratefulDeadConcerts

Note: Random-generated data is used in the

demodb

, including data used for Emails, Names, Surnames, Phone Numbers and Reviews.

Version
demodb

has a version that, in general, is not linked to the Server version you are running. You can check the version of the

demodb

included in your distribution by executing the following SQL query:
SELECT `Version` FROM `DBInfo`;

Current version is 0.76.

Location
The demo database is located in the
3.0.0\databases\demodb

databases

directory under your

$ORIENTDB_HOME

(e.g.

D:\orientdb\orientdb-community-

.

Connecting to the Demo Database
It is possible to connect to
read

/

demodb

using the three standard OrientDB Users:

read

write

/

write

admin

/

admin

Using the Demo Database with OrientDB 2.2.x
The demo database can be easily loaded into OrientDB 2.2.x using the Studio's "Import a public database" feature.
Alternatively, it is possible to import it via an SQL script that includes the set of instructions needed to recreate the data model as well
as all the records (vertices, edges, and documents).

78

Data M odel

Data Model
demodb

is the database of an hypothetical Travel Agency that runs a public social platform as well.

Users (that are stored in the database in the class Profiles) can freely register to the social platform and start making friends (friendship
is expressed via the HasFriend edge).
Some of the users can become customers. When this happens the application in use at the Social Travel Agency creates a vertex in the
Customers class and links it to the associated profile via an HasProfile edge.
When customers are created, they are automatically linked to a country as well, via an IsFromCountry edge. Countries are stored in the
Countries vertex class.
Orders made by customers are stored in the vertex class Orders. Each customer can make one or more orders, and the HasCustomer
edge is used to connect orders to customers.
When customers start visiting Attractions (like Castles, Monuments, Theatres or Archaeological Sites) or using Services (like Hotels or
Restaurants) edges are created to link that specific customer with that specific attraction or service (HasVisited, HasStayed, and
HasEaten edges are used).
The Social Travel Agency also stores some reviews in the vertex class Reviews. Reviews are linked to customers via the MadeReview
edge, and to an attraction or service via the HasReview edge.
Data model of

demodb

v.0.76 is reported in the image below:

Inheritance
79

Data M odel
Inheritance in the Vertex and Edge classes of

demodb

v.0.76 is reported in the image below:

80

Queries

Queries
This Section includes several query examples that you can execute from the Studio's Browse Tab, or from its Graph Editor. You may
also execute these queries directly from the Console, or your application through an API or Driver.
Note: the screen-shots included in this Section have been taken with version 0.76 of the demo database. While the queries remain valid,
future versions of the demo database may include different records.
The following table can help you navigate through all examples:
Category
Profiles

Friendship

Customers

Countries

Orders

Question

Link

Find the 'year of birth' of the Profiles, and how many Profiles were born in the same
year

Link

Find the top 3 Profiles that have the highest number of Friends

Link

Find Santo's Friends

Link

Find Santo's Friends who are also Customers

Link

Find Santo's Friends who are also Customers, and the Countries they are from

Link

Find Santo's Friends who are also Customers, and the Orders they have placed

Link

Among Santo's Friends, find the top 3 Customers that placed the highest number of
Orders

Link

Among Santo's Friends, find the top 3 Customers that visited the highest number of
Places

Link

Find all the Friends of Customer identified with OrderedId 1 that are not Customers (so
that a product can be proposed)

Link

Find everything that is connected (1st degree) to Customer with OrderedId 1

Link

Find all Locations connected to Customer with OrderedId 1

Link

Find all Locations connected to Customer with OrderedId 1, and their Reviews (if any)

Link

Find the other Customers that visited the Locations visited by Customer with OrderedId
1

Link

Find all the places where Customer with OrderedId 2 has stayed

Link

Find all places where Customer with Id 1 has eaten

Link

Find the 3 Customers who made more reviews

Link

Find all Orders placed by Customer with OrderedId 2

Link

Calculate the total revenues from Orders associated with Customer with OrderedId 2

Link

Find the 3 Customers who placed most Orders

Link

Find the top 3 Countries from where Customers are from

Link

Find the top 3 Countries from where Customers are from

Link

Find Santo's Friends who are also Customers, and the Countries they are from

Link

Calculate the total revenues from Orders, and the min, max and average Order amount

Link

Find the year of the Orders, and how many Orders have been placed in the same year

Link

Find the 3 Customers who placed most Orders

Link

Find the top 3 Customers in terms of spending

Link

Find all Orders placed by Customer with Id 2

Link

Calculate the total revenues from Orders associated with Customer with Id 2

Link

81

Queries
Attractions

Find all Attractions connected with Customer with OrderedId 1

Link

S ervices

Find all Services connected with Customer with OrderedId 1

Link

Find the 3 Hotels that have been booked most times

Link

Find the 3 Hotels that have most reviews

Link

Find the top 3 nationality of the tourists that have eaten at Restaurant with Id 26

Link

Find all Locations visited by Santo

Link

Find all Locations connected to Customer with OrderedId 1

Link

Find all Locations connected to Customer with OrderedId 1, and their Reviews (if any)

Link

Find all Locations visited by Customer with OrderedId 2

Link

Find all Locations visited by Santo's friends

Link

Find number of Reviews per star

Link

Find all reviewed Services

Link

Find all reviewed Services and the Customer who made the review

Link

Find the numbers of reviews per Service

Link

Find the 3 Hotels that have most reviews

Link

Find the 3 Customers who made more reviews

Link

Recommend some friends to Profile 'Isabella Gomez' (friends of friends)

Link

Recommend some Hotels to Customer with OrderedId 1

Link

Find all the Friends of Customer identified with OrderedId 1 that are not Customers (so
that a product can be proposed)

Link

Find all the Customer Friends that are not Customers (so that a product can be
proposed)

Link

Find all Locations (Services + Attractions) connected with Customer with OrderedId 1

Link

Find the 3 Services (Hotels + Restaurants) that have most reviews

Link

Find the shortest path between the Profile 'Santo' and the Country 'United States'

Link

Find the shortest path between the Profile 'Santo' and the Restaurant 'M alga Granezza'

Link

Traverse everything from Profile 'Santo' up to depth three

Link

Traverse everything from Country 'Italy' up to depth three

Link

Locations

Reviews

Recommendations

Business
Opportunities

Polymorphism

S hortest Paths

Traverses

82

Queries

Profiles
Example 1
Find the 'year of birth' of the Profiles, and how many Profiles were born in the same year:
SELECT
count(*) as NumberOfProfiles,
Birthday.format('yyyy') AS YearOfBirth
FROM Profiles
GROUP BY YearOfBirth
ORDER BY NumberOfProfiles DESC

In the Browse Tab of Studio, using the query above, this is the obtained list of records (only few records are shown in the image below):

Note: in v. 2.x the corresponding query is:
SELECT
count(*) as NumberOfProfiles,
YearOfBirth
FROM (
SELECT
Birthday.format('yyyy') AS YearOfBirth
FROM Profiles)
GROUP BY YearOfBirth
ORDER BY NumberOfProfiles DESC

Example 2
Find the top 3 Profiles that have the highest number of Friends:
SELECT
@rid as Profile_RID,
Name,
Surname,
both('HasFriend').size() AS FriendsNumber
FROM `Profiles`
ORDER BY FriendsNumber DESC
LIMIT 3

In the Browse Tab of Studio, using the query above, this is the obtained list of records:

83

Queries

84

Queries

Friendship
Example 1
Find Santo's Friends:
MATCH {Class: Profiles, as: profile, where: (Name='Santo' AND Surname='OrientDB')}-HasFriend-{Class: Profiles, as: friend}
RETURN $pathelements

In the Graph Editor included in Studio, using 'RETURN $pathelements' as

RETURN

clause, this is the obtained graph:

In the Browse Tab of Studio, using 'RETURN friend.@Rid as Friend_RID, friend.Name as Friend_Name, friend.Surname as
Friend_Surname' as

RETURN

clause, this is the obtained list of records (only few records are shown in the image below):

If you would like only to count them, you can execute a query like the following:
SELECT COUNT(*)
FROM (
MATCH {Class: Profiles, as: profile, where: (Name='Santo' AND Surname='OrientDB')}-HasFriend-{Class: Profiles, as: friend}
RETURN friend
)

or

85

Queries
SELECT
both('HasFriend').size() AS FriendsNumber
FROM `Profiles`
WHERE Name='Santo' AND Surname='OrientDB'

Example 2
Find Santo's Friends who are also Customers:
MATCH {Class: Profiles, as: profile, where: (Name='Santo' AND Surname='OrientDB')}-HasFriend-{Class: Profiles, as: friend}<-Ha
sProfile-{class: Customers, as: customer}
RETURN $pathelements

In the Graph Editor included in Studio, using 'RETURN $pathelements' as

RETURN

clause, this is the obtained graph:

In the Browse Tab of Studio, using 'RETURN friend.@Rid as Friend_RID, friend.Name as Friend_Name, friend.Surname as
Friend_Surname, customer.@Rid as Customer_RID, customer.OrderedId as Customer_OrederedId' as

RETURN

clause, this is the

obtained list of records (only few records are shown in the image below):

Example 3
Find Santo's Friends who are also Customers, and the Countries they are from:

86

Queries
MATCH {Class: Profiles, as: profile, where: (Name='Santo' AND Surname='OrientDB')}-HasFriend-{Class: Profiles, as: friend}<-Ha
sProfile-{class: Customers, as: customer}-IsFromCountry->{Class: Countries, as: country}
RETURN $pathelements

In the Graph Editor included in Studio, using 'RETURN $pathelements' as

RETURN

clause, this is the obtained graph:

In the Browse Tab of Studio, using 'RETURN friend.@Rid as Friend_RID, friend.Name as Friend_Name, friend.Surname as
Friend_Surname, customer.@Rid as Customer_RID, customer.OrderedId as Customer_OrederedId, country.Name as FriendIsFrom' as
RETURN

clause, this is the obtained list of records (only few records are shown in the image below):

Example 4
Find Santo's Friends who are also Customers, and the Orders they have placed:
MATCH {Class: Profiles, as: profile, where: (Name='Santo' AND Surname='OrientDB')}-HasFriend-{Class: Profiles, as: friend}<-Ha
sProfile-{class: Customers, as: customer}<-HasCustomer-{Class: Orders, as: order}
RETURN $pathelements

In the Graph Editor included in Studio, using 'RETURN $pathelements' as

RETURN

clause, this is the obtained graph:

87

Queries

In the Browse Tab of Studio, using 'RETURN friend.@Rid as Friend_RID, friend.Name as Friend_Name, friend.Surname as
Friend_Surname, customer.@Rid as Customer_RID, customer.OrderedId as Customer_OrederedId, order.Id as OrderId' as

RETURN

clause, this is the obtained list of records (only few records are shown in the image below):

Example 5
Among Santo's Friends, find the top 3 Customers that placed the highest number of Orders:

88

Queries
SELECT
OrderedId as Customer_OrderedId,
in('HasCustomer').size() as NumberOfOrders,
out('HasProfile').Name as Friend_Name,
out('HasProfile').Surname as Friend_Surname
FROM (
SELECT expand(customer)
FROM (
MATCH {Class: Profiles, as: profile, where: (Name='Santo' AND Surname='OrientDB')}-HasFriend-{Class: Profiles, as: friend}
<-HasProfile-{class: Customers, as: customer}
RETURN customer
)
)
ORDER BY NumberOfOrders DESC
LIMIT 3

In the Browse Tab of Studio, using the query above, this is the obtained list of records:

Example 6
Among Santo's Friends, find the top 3 Customers that visited the highest number of Places:
SELECT
OrderedId as Customer_OrderedId,
out('HasVisited').size() as NumberOfVisits,
out('HasProfile').Name as Friend_Name,
out('HasProfile').Surname as Friend_Surname
FROM (
SELECT expand(customer)
FROM (
MATCH {Class: Profiles, as: profile, where: (Name='Santo' AND Surname='OrientDB')}-HasFriend-{Class: Profiles, as: friend}
<-HasProfile-{class: Customers, as: customer}
RETURN customer
)
)
ORDER BY NumberOfVisits DESC
LIMIT 3

In the Browse Tab of Studio, using the query above, this is the obtained list of records:

89

Queries
You may find in a similar way the top 3 Customers, among Santo's Friends, that have stayed at the highest number of Hotels, or have
eaten at the highest number of Restaurants. Just use
out("HasVisited").size()
NumberOfRestaurants

out("HasStayed").size()

(you may also consider to modify the alias, from

or

out("HasEaten").size()

NumberOfVisits

to

instead of

NumberOfHotels

and

, so that it is more coherent to these cases).

Example 7
Find all the Friends of Customer identified with OrderedId 1 that are not Customers (so that a product can be proposed):
SELECT
@Rid as Friend_RID,
Name as Friend_Name,
Surname as Friend_Surname
FROM (
SELECT expand(customerFriend)
FROM (
MATCH {Class:Customers, as: customer, where:(OrderedId=1)}-HasProfile-{Class:Profiles, as: profile}-HasFriend-{Class:Profi
les, as: customerFriend} RETURN customerFriend
)
)
WHERE in('HasProfile').size()=0
ORDER BY Friend_Name ASC

In the Browse Tab of Studio, using the query above, this is the obtained list of records (only few records are shown in the image below):

or, without restricting to a specific customer:
Find all the Customer Friends that are not Customers (so that a product can be proposed):
In the Graph Editor included in Studio, using the query below, this is the obtained graph:
SELECT *
FROM (
SELECT expand(customerFriend)
FROM (
MATCH {Class:Customers, as: customer}-HasProfile-{Class:Profiles, as: profile}-HasFriend-{Class:Profiles, as: customerFrie
nd}
RETURN customerFriend
)
)
WHERE in('HasProfile').size()=0

90

Queries

In the Browse Tab of Studio, using the query below, this is the obtained list of records (only few records are shown in the image below):
SELECT
@Rid as Friend_RID,
Name as Friend_Name,
Surname as Friend_Surname
FROM (
SELECT expand(customerFriend)
FROM (
MATCH {Class:Customers, as: customer}-HasProfile-{Class:Profiles, as: profile}-HasFriend-{Class:Profiles, as: customerFrie
nd}
RETURN customerFriend
)
)
WHERE in('HasProfile').size()=0

91

Queries

Customers
Example 1
Find everything that is connected (1st degree) to Customer with OrderedId 1:
MATCH {class: Customers, as: c, where: (OrderedId=1)}--{as: n}
RETURN $pathelements

In the Graph Editor included in Studio, using 'RETURN $pathelements' as

RETURN

clause, this is the obtained graph:

Example 2
Find all Locations connected to Customer with OrderedId 1:
MATCH {class: Customers, as: customer, where: (OrderedId=1)}--{Class: Locations}
RETURN $pathelements

In the Graph Editor included in Studio, using 'RETURN $pathelements' as

RETURN

clause, this is the obtained graph:

92

Queries

Example 3
Find all Locations connected to Customer with OrderedId 1, and their Reviews (if any):
MATCH {class: Customers, as: c, where: (OrderedId=1)}--{class: Locations, as: loc}-HasReview->{class: Reviews, as: r, optional
: true}
RETURN $pathelements

In the Graph Editor included in Studio, using 'RETURN $pathelements' as

RETURN

clause, this is the obtained graph:

Example 4
Find the other Customers that visited the Locations visited by Customer with OrderedId 1:

93

Queries
MATCH {class: Customers, as: customer, where: (OrderedId=1)}--{class: Locations, as: loc}--{class: Customers, as: otherCustome
rs, where: (OrderedId<>1)}
RETURN $pathelements

In the Graph Editor included in Studio, using 'RETURN $pathelements' as

RETURN

clause, this is the obtained graph:

If we want to return also also their Profile names, surnames and emails:
MATCH {class: Customers, as: customer, where: (OrderedId=1)}--{class: Locations, as: loc}--{class: Customers, as: otherCustome
rs, where: (OrderedId<>1)}-HasProfile->{class: Profiles, as: profile}
RETURN otherCustomers.OrderedId, profile.Name, profile.Surname, profile.Email
ORDER BY `otherCustomers.OrderedId` ASC

In the Browse Tab of Studio, using 'RETURN otherCustomers.OrderedId, profile.Name, profile.Surname, profile.Email' as

RETURN

clause, this is the obtained list of records (only few records are shown in the image below):

Example 5
Find all the places where Customer with OrderedId 2 has stayed:

94

Queries
MATCH {as: n}<-HasStayed-{class: Customers, as: c, where: (OrderedId=2)}
RETURN $pathelements

In the Graph Editor included in Studio, using 'RETURN $pathelements' as

RETURN

clause, this is the obtained graph:

Example 6
Find all places where Customer with OrderedId 1 has eaten:
MATCH {as: n}<-HasEaten-{class: Customers, as: c, where: (OrderedId=1)}
RETURN $pathelements

In the Graph Editor included in Studio, using 'RETURN $pathelements' as

RETURN

clause, this is the obtained graph:

Example 7

95

Queries
Find the 3 Customers who made more reviews:
SELECT
OrderedId as CustomerId,
out("MadeReview").size() AS ReviewNumbers
FROM `Customers`
ORDER BY ReviewNumbers DESC
LIMIT 3

In the Browse Tab of Studio, using the query above, this is the obtained list of records:

Example 8
Find all Orders placed by Customer with Id 2:
MATCH {class: Customers, as: c, where: (OrderedId=1)}<-HasCustomer-{class: Orders, as: o}
RETURN $pathelements

In the Graph Editor included in Studio, using 'RETURN $pathelements' as

RETURN

clause, this is the obtained graph:

Example 9
Calculate the total revenues from Orders associated with Customer with Id 2:

96

Queries
SELECT sum(Amount) as TotalAmount
FROM (
SELECT expand(in('HasCustomer'))
FROM Customers
WHERE OrderedId=2
)

In the Browse Tab of Studio, using the query above, this is the obtained list of records:

Example 10
Find the 3 Customers who placed most Orders:
SELECT
OrderedId as CustomerId,
in("HasCustomer").size() AS NumberOfOrders
FROM Customers
ORDER BY NumberOfOrders
DESC LIMIT 3

In the Browse Tab of Studio, using the query above, this is the visualized result:

Example 11
Find the top 3 Countries from where Customers are from:
SELECT
Name as CountryName,
in('IsFromCountry').size() as NumberOfCustomers
FROM Countries
ORDER BY NumberOfCustomers DESC
LIMIT 3

97

Queries
In the Browse Tab of Studio, using the query above, this is the obtained list of records:

98

Queries

Countries
Example 1
Find the top 3 Countries from where Customers are from:
SELECT
Name as CountryName,
in('IsFromCountry').size() as NumberOfCustomers
FROM Countries
ORDER BY NumberOfCustomers DESC
LIMIT 3

In the Browse Tab of Studio, using the query above, this is the obtained list of records:

Example 2
Find Santo's Friends who are also Customers, and the Countries they are from:
MATCH {Class: Profiles, as: profile, where: (Name='Santo' AND Surname='OrientDB')}-HasFriend-{Class: Profiles, as: friend}<-Ha
sProfile-{class: Customers, as: customer}-IsFromCountry->{Class: Countries, as: country}
RETURN $pathelements

In the Graph Editor included in Studio, using 'RETURN $pathelements' as

RETURN

clause, this is the obtained graph:

99

Queries

In the Browse Tab of Studio, using 'RETURN friend.@Rid as Friend_RID, friend.Name as Friend_Name, friend.Surname as
Friend_Surname, customer.@Rid as Customer_RID, customer.OrderedId as Customer_OrederedId, country.Name as FriendIsFrom' as
RETURN

clause, this is the obtained list of records (only few records are shown in the image below):

100

Queries

Orders
Example 1
Calculate the total revenues from Orders, and the min, max and average Order amount:
SELECT
count(*) as OrdersNumber,
sum(Amount) AS TotalRevenuesFromOrders,
min(Amount) as MinAmount,
(sum(Amount)/count(*)) as AverageAmount,
max(Amount) as MaxAmount
FROM Orders

In the Browse Tab of Studio, using the query above, this is the visualized result:

Example 2
Find the year of the Orders, and how many Orders have been placed in the same year:
SELECT
count(*) as OrdersCount,
OrderDate.format('yyyy') AS OrderYear
FROM Orders
GROUP BY OrderYear
ORDER BY OrdersCount DESC

In the Browse Tab of Studio, using the query above, this is the visualized result:

101

Queries

Example 3
Find the 3 Customers who placed most Orders:
SELECT
OrderedId as CustomerId,
in("HasCustomer").size() AS NumberOfOrders
FROM Customers
ORDER BY NumberOfOrders
DESC LIMIT 3

In the Browse Tab of Studio, using the query above, this is the visualized result:

Example 4
Find the top 3 Customers in terms of spending:
SELECT
customer.OrderedId as customerOrderedId,
SUM(order.Amount) as totalAmount
FROM (
MATCH {Class: Customers, as: customer}<-HasCustomer-{class: Orders, as: order}
RETURN customer, order
)
GROUP BY customerOrderedId
ORDER BY totalAmount DESC
LIMIT 3

102

Queries
In the Browse Tab of Studio, using the query above, this is the visualized result:

Example 5
Find all Orders placed by Customer with Id 2:
MATCH {class: Customers, as: c, where: (OrderedId=1)}<-HasCustomer-{class: Orders, as: o}
RETURN $pathelements

In the Graph Editor included in Studio, using 'RETURN $pathelements' as

RETURN

clause, this is the obtained graph:

Example 6
Calculate the total revenues from Orders associated with Customer with Id 2:
SELECT sum(Amount) as TotalAmount
FROM (
SELECT expand(in('HasCustomer'))
FROM Customers
WHERE OrderedId=2
)

103

Queries
In the Browse Tab of Studio, using the query above, this is the obtained list of records:

104

Queries

Attractions
Example 1
Find all Attractions connected with Customer with OrderedId 1:
MATCH {class: Customers, as: customer, where: (OrderedId=1)}--{Class: Attractions, as: attraction}
RETURN $pathelements

In the Graph Editor included in Studio, using 'RETURN $pathelements' as

RETURN

clause, this is the obtained graph:

In the Browse Tab of Studio, using 'RETURN attraction.@Rid as Attraction_RID, attraction.Name as Attraction_Name, attraction.Type
as Attraction_Type' as

RETURN

clause, this is the obtained list of records (only few records are shown in the image below):

105

Queries

Services
Example 1
Find all Services connected with Customer with OrderedId 1:
MATCH {class: Customers, as: customer, where: (OrderedId=1)}--{Class: Services, as: service}
RETURN $pathelements

In the Graph Editor included in Studio, using 'RETURN $pathelements' as

RETURN

clause, this is the obtained graph:

In the Browse Tab of Studio, using 'RETURN service.@Rid as Service_RID, service.Name as Service_Name, service.Type as
Service_Type' as

RETURN

clause, this is the obtained list of records (only few records are shown in the image below):

Example 2
Find the 3 Hotels that have been booked most times:

106

Queries
SELECT
Name, Type, in("HasStayed").size() AS NumberOfBookings
FROM Hotels
ORDER BY NumberOfBookings DESC
LIMIT 3

In the Browse Tab of Studio, using the query below, this is the obtained list of records:

In a similar way:
Find the 3 Restaurants that have been used most times:
SELECT
Name, Type, in("HasEaten").size() AS VisitsNumber
FROM Restaurants
ORDER BY VisitsNumber DESC
LIMIT 3

In the Browse Tab of Studio, using the query below, this is the obtained list of records:

Example 3
Find the 3 Hotels that have most reviews:
SELECT
Name, Type, out("HasReview").size() AS ReviewNumbers
FROM `Hotels`
ORDER BY ReviewNumbers DESC
LIMIT 3

In the Browse Tab of Studio, using the query below, this is the obtained list of records:

107

Queries

In a similar way:
Find the 3 Restaurants that have most reviews :
SELECT
Name, Type, out("HasReview").size() AS ReviewNumbers
FROM `Restaurants`
ORDER BY ReviewNumbers DESC
LIMIT 3

In the Browse Tab of Studio, using the query below, this is the obtained list of records:

Example 4
Find the top 3 nationality of the tourists that have eaten at Restaurant with Id 26:
SELECT
Name,
count(*) as CountryCount
FROM (
SELECT
expand(out('IsFromCountry')) AS countries
FROM (
SELECT
expand(in("HasEaten")) AS customers
FROM Restaurants
WHERE Id='26'
UNWIND customers)
UNWIND countries)
GROUP BY Name
ORDER BY CountryCount DESC
LIMIT 3

In the Browse Tab of Studio, using the query below, this is the obtained list of records:

108

Queries

In a similar way:
Find the top 3 nationality of the tourists that stayed at Hotel with Id 627:
SELECT
Name, count(*) as CountryCount
FROM (
SELECT
expand(out('IsFromCountry')) AS countries
FROM (
SELECT
expand(in("HasStayed")) AS customers
FROM Hotels
WHERE Id='627'
UNWIND customers)
UNWIND countries)
GROUP BY Name
ORDER BY CountryCount DESC
LIMIT 3

In the Browse Tab of Studio, using the query below, this is the obtained list of records:

109

Queries

Locations
Example 1
Find all Locations visited by Santo:
MATCH {Class: Profiles, as: profile, where: (Name='Santo' AND Surname='OrientDB')}<-HasProfile-{Class: Customers, as: customer
}-HasVisited->{class: Locations, as: location}
RETURN $pathelements

In the Graph Editor included in Studio, using the query above, this is the obtained graph:

Example 2
Find all Locations connected to Customer with OrderedId 1:
MATCH {class: Customers, as: customer, where: (OrderedId=1)}--{Class: Locations}
RETURN $pathelements

In the Graph Editor included in Studio, using 'RETURN $pathelements' as

RETURN

clause, this is the obtained graph:

110

Queries

Example 3
Find all Locations connected to Customer with OrderedId 1, and their Reviews (if any):
MATCH {class: Customers, as: c, where: (OrderedId=1)}--{class: Locations, as: loc}-HasReview->{class: Reviews, as: r, optional
: true}
RETURN $pathelements

In the Graph Editor included in Studio, using 'RETURN $pathelements' as

RETURN

clause, this is the obtained graph:

Example 4
Find all Locations visited by Customer with OrderedId 2:
MATCH {Class: Locations, as: location}<-HasVisited-{class: Customers, as: customer, where: (OrderedId=2)}
RETURN $pathelements

111

Queries
In the Graph Editor included in Studio, using 'RETURN $pathelements' as

RETURN

clause, this is the obtained graph:

In the Browse Tab of Studio, using 'RETURN location.@Rid as Location_RID, location.Name as Location_Name, location.Type as
Location_Type' as

RETURN

clause, this is the obtained list of records (only few records are shown in the image below):

Example 5
Find all Locations visited by Santo's friends:
MATCH {Class: Profiles, as: profile, where: (Name='Santo' and Surname='OrientDB')}-HasFriend->{Class: Profiles, as: friend}<-H
asProfile-{Class: Customers, as: customer}-HasVisited->{Class: Locations, as: location}
RETURN $pathelements

In the Graph Editor included in Studio, using 'RETURN $pathelements' as

RETURN

clause, this is the obtained graph:

112

Queries

In the Browse Tab of Studio, using 'location.@Rid as Location_RID, location.Name as Location_Name, location.Type as Location_Type,
friend.Name as Friend_Name, friend.Surname as Friend_Surname' as

RETURN

clause, this is the obtained list of records (only few

records are shown in the image below):

113

Queries

Reviews
Example 1
Find number of Reviews per star:
SELECT
Stars, count(*) as Count
FROM HasReview
GROUP BY Stars
ORDER BY Count DESC

In the Browse Tab of Studio, using the query above, this is the obtained list of records:

Example 2
Find all reviewed Services:
MATCH {class: Services, as: s}-HasReview->{class: Reviews, as: r}
RETURN $pathelements

In the Graph Editor included in Studio, using the query above, this is the obtained graph:

114

Queries

Example 3
Find all reviewed Services and the Customer who made the review:
MATCH {class: Services, as: s}-HasReview->{class: Reviews, as: r}<-MadeReview-{class: Customers, as: c}
RETURN $pathelements

In the Graph Editor included in Studio, using the query above, this is the obtained graph:

Example 4
Find the numbers of reviews per Service:

115

Queries
SELECT
@rid as Service_RID,
Name as Service_Name,
Type as Service_Type,
out("HasReview").size() AS ReviewNumbers
FROM `Services`
ORDER BY ReviewNumbers DESC

In the Browse Tab of Studio, using the query above, this is the obtained list of records:

Example 5
Find the 3 Hotels that have most reviews:
SELECT
@rid as Hotel_RID,
Name as Hotel_Name,
Type as Hotel_Type,
out("HasReview").size() AS ReviewNumbers
FROM `Hotels`
ORDER BY ReviewNumbers DESC
LIMIT 3

In the Browse Tab of Studio, using the query above, this is the obtained list of records:

In a similar way:
Find the 3 Restaurants that have most reviews:

116

Queries
SELECT
@rid as Restaurant_RID,
Name as Restaurants_Name,
Type as Restaurants_Type,
out("HasReview").size() AS ReviewNumbers
FROM `Restaurants`
ORDER BY ReviewNumbers DESC
LIMIT 3

In the Browse Tab of Studio, using the query above, this is the obtained list of records:

In a polymorphic way:
Find the 3 Services (Hotels + Restaurants) that have most reviews:
SELECT
@rid as Service_RID,
Name as Service_Name,
Type as Service_Type,
out("HasReview").size() AS ReviewNumbers
FROM `Services`
ORDER BY ReviewNumbers DESC
LIMIT 3

In the Browse Tab of Studio, using the query above, this is the obtained list of records:

Example 6
Find the 3 Customers who made more reviews:

117

Queries
SELECT
OrderedId as CustomerId,
out("MadeReview").size() AS ReviewNumbers
FROM `Customers`
ORDER BY ReviewNumbers DESC
LIMIT 3

In the Browse Tab of Studio, using the query above, this is the obtained list of records:

118

Queries

Recommendations
Example 1
Recommend some friends to Profile 'Isabella Gomez' (friends of friends):
MATCH
{class: Profiles, as: profile, where: (Name = 'Isabella' AND Surname='Gomez')}-HasFriend-{as: friend},
{as: friend}-HasFriend-{as: friendOfFriend, where: ($matched.profile not in $currentMatch.both('HasFriend') and $matched.pro
file != $currentMatch)}
RETURN DISTINCT friendOfFriend.Name

In the Browse Tab of Studio, using the query above, this is the obtained list of records (only few records are shown in the image below):

Example 2
Recommend some Hotels to Customer with OrderedId 1:
MATCH
{Class: Customers, as: customer, where: (OrderedId=1)}-HasProfile->{class: Profiles, as: profile},
{as: profile}-HasFriend->{class: Profiles, as: friend},
{as: friend}<-HasProfile-{Class: Customers, as: customerFriend},
{as: customerFriend}-HasStayed->{Class: Hotels, as: hotel},
{as: customerFriend}-MadeReview->{Class: Reviews, as: review},
{as: hotel}-HasReview->{as: review}
RETURN $pathelements

In the Graph Editor included in Studio, using 'RETURN $pathelements' as

RETURN

clause, this is the obtained graph:

119

Queries

To filter additionally, and suggest only the 4 and 5-rated hotels, it is possible to add a filter condition on the 'HasReview' edge (property
'Stars'):
MATCH
{Class: Customers, as: customer, where: (OrderedId=1)}-HasProfile->{class: Profiles, as: profile},
{as: profile}-HasFriend->{class: Profiles, as: friend},
{as: friend}<-HasProfile-{Class: Customers, as: customerFriend},
{as: customerFriend}-HasStayed->{Class: Hotels, as: hotel},
{as: customerFriend}-MadeReview->{Class: Reviews, as: review},
{as: hotel}.outE('HasReview'){as: ReviewStars, where: (Stars>3)}.inV(){as: review}
RETURN $pathelements

In the Graph Editor included in Studio, using 'RETURN $pathelements' as

RETURN

clause, this is the obtained graph:

120

Queries

Business Opportunities
Example 1
Find all the Friends of Customer identified with OrderedId 1 that are not Customers (so that a product can be proposed):
SELECT
@Rid as Friend_RID,
Name as Friend_Name,
Surname as Friend_Surname
FROM (
SELECT expand(customerFriend)
FROM (
MATCH {Class:Customers, as: customer, where:(OrderedId=1)}-HasProfile-{Class:Profiles, as: profile}-HasFriend-{Class:Profi
les, as: customerFriend} RETURN customerFriend
)
)
WHERE in('HasProfile').size()=0
ORDER BY Friend_Name ASC

In the Browse Tab of Studio, using the query above, this is the obtained list of records (only few records are shown in the image below):

Example 2
Find all the Customer Friends that are not Customers (so that a product can be proposed).
In the Graph Editor included in Studio, using the query below, this is the obtained graph:
SELECT DISTINCT * FROM (
SELECT expand(customerFriend)
FROM (
MATCH
{Class:Customers, as: customer}-HasProfile-{Class:Profiles, as: profile}-HasFriend-{Class:Profiles, as: customerFriend}
RETURN customerFriend
)
)
WHERE in('HasProfile').size()=0

121

Queries

In the Browse Tab of Studio, using the query below, this is the obtained list of records (only few records are shown in the image below):
SELECT DISTINCT @Rid as Friend_RID, Name as Friend_Name, Surname as Friend_Surname
FROM (
SELECT expand(customerFriend)
FROM (
MATCH
{Class:Customers, as: customer}-HasProfile-{Class:Profiles, as: profile}-HasFriend-{Class:Profiles, as: customerFriend}
RETURN customerFriend
)
)
WHERE in('HasProfile').size()=0
ORDER BY Friend_RID

122

Queries

Polymorphism
Example 1
Find all Locations (Services + Attractions) connected with Customer with OrderedId 1:
MATCH {class: Customers, as: customer, where: (OrderedId=1)}--{Class: Locations, as: location}
RETURN $pathelements

In the Graph Editor included in Studio, using 'RETURN $pathelements' as

RETURN

clause, this is the obtained graph:

In the Browse Tab of Studio, using 'RETURN location.@Rid as Location_RID, location.Name as Location_Name, location.Type as
Location_Type' as

RETURN

clause, this is the obtained list of records (only few records are shown in the image below):

Example 2
Find the 3 Hotels that have most reviews:

123

Queries
SELECT
@rid as Hotel_RID,
Name as Hotel_Name,
Type as Hotel_Type,
out("HasReview").size() AS ReviewNumbers
FROM `Hotels`
ORDER BY ReviewNumbers DESC
LIMIT 3

In the Browse Tab of Studio, using the query above, this is the obtained list of records:

In a similar way:
Find the 3 Restaurants that have most reviews:
SELECT
@rid as Restaurant_RID,
Name as Restaurants_Name,
Type as Restaurants_Type,
out("HasReview").size() AS ReviewNumbers
FROM `Restaurants`
ORDER BY ReviewNumbers DESC
LIMIT 3

In the Browse Tab of Studio, using the query above, this is the obtained list of records:

In a polymorphic way:
Find the 3 Services (Hotels + Restaurants) that have most reviews:

124

Queries
SELECT
@rid as Service_RID,
Name as Service_Name,
Type as Service_Type,
out("HasReview").size() AS ReviewNumbers
FROM `Services`
ORDER BY ReviewNumbers DESC
LIMIT 3

In the Browse Tab of Studio, using the query above, this is the obtained list of records:

125

Queries

Shortest Paths
Example 1
Find the shortest path between the Profile 'Santo' and the Country 'United States':
SELECT expand(path) FROM (
SELECT shortestPath($from, $to) AS path
LET
$from = (SELECT FROM Profiles WHERE Name='Santo' and Surname='OrientDB'),
$to = (SELECT FROM Countries WHERE Name='United States')
UNWIND path
)

In the Graph Editor included in Studio, this is the obtained graph:

In the Browse Tab of Studio, this is the obtained list of records:

Example 2
126

Queries
Find the shortest path between the Profile 'Santo' and the Restaurant 'M alga Granezza':
SELECT expand(path) FROM (
SELECT shortestPath($from, $to) AS path
LET
$from = (SELECT FROM Profiles WHERE Name='Santo' and Surname='OrientDB'),
$to = (SELECT FROM Restaurants WHERE Name='Malga Granezza')
UNWIND path
)

In the Graph Editor included in Studio, this is the obtained graph:

In the Browse Tab of Studio, this is the obtained list of records:

127

Queries

Traverses
Example 1
Traverse everything from Profile 'Santo' up to depth three:
TRAVERSE * FROM (
SELECT FROM Profiles WHERE Name='Santo' and Surname='OrientDB'
) MAXDEPTH 3

In the Graph Editor included in Studio, this is the obtained graph:

In the Browse Tab of Studio, this is the obtained list of records (only few records are shown in the image below):

Example 2
Traverse everything from Country 'Italy' up to depth three:

128

Queries
TRAVERSE * FROM (
SELECT FROM Countries WHERE Name='Italy'
) MAXDEPTH 3

In the Graph Editor included in Studio, this is the obtained graph:

In the Browse Tab of Studio, this is the obtained list of records (only few records are shown in the image below):

129

Graph Portions

Graph Portions
This Section includes some screen-shots on "portions" of the

demodb

graph.

Note: the screen-shots included in this Section have been taken with version 0.76 of the demo database. While the queries remain valid,
future versions of the demo database may include different records.

Profiles
The graph below includes vertices in the Profiles class.
Some profiles have no friends, and ten profile "communities" are easily identifiable (a "community" is a group of highly connected
profiles):

Customers' Friends
The graph below shows the relationships between all customers and their friends.
All customer vertices are connected to their corresponding profiles in the social platform. The profiles may have friends, or not.

130

Graph Portions

Customer-Country Relationship
The graph below shows the relationships between all customers and their countries of origin:

Customer-Restaurant Relationship
Relationships between customers and restaurants are reported in the graph below:

131

Graph Portions

132

Basic SQL

SQL
M ost NoSQL products employ a custom query language. In this, OrientDB differs by focusing on standards in query languages. That is,
instead of inventing "Yet Another Query Language," it begins with the widely used and well-understood language of SQL. It then
extends SQL to support more complex graphing concepts, such as Trees and Graphs.
Why SQL? Because SQL is ubiquitous in the database development world. It is familiar and more readable and concise than its
competitors, such as M ap Reduce scripts or JSON based querying.

SELECT
The

statement queries the database and returns results that match the given parameters. For instance, earlier in Getting Started,

SELECT

two queries were presented that gave the same results:
available through a
orientdb>

SELECT

BROWSE CLUSTER ouser

and

BROWSE CLASS OUser

. Here is a third option,

statement.

SELECT FROM OUser

Notice that the query has no projections. This means that you do not need to enter a character to indicate that the query should return
the entire record, such as the asterisk in the Relational model, (that is,

SELECT * FROM OUser

).

Additionally, OUser is a class. By default, OrientDB executes queries against classes. Targets can also be:
Clusters To execute against a cluster, rather than a class, prefix
orientdb>

CLUSTER

to the target name.

SELECT FROM CLUSTER:Ouser

Record ID To execute against one or more Record ID's, use the identifier(s) as your target. For example.
orientdb>

SELECT FROM #10:3

orientdb>

SELECT FROM [#10:1, #10:30, #10:5]

Indexes To execute a query against an index, prefix
orientdb>

INDEX

to the target name.

SELECT VALUE FROM INDEX:dictionary WHERE key='Jay'

WHERE
M uch like the standard implementation of SQL, OrientDB supports
orientdb>

This returns all
WHERE

WHERE

conditions to filter the returning records too. For example,

SELECT FROM OUser WHERE name LIKE 'l%'

OUser

records where the name begins with

l

. For more information on supported operators and functions, see

.

ORDER BY
In addition to

WHERE

, OrientDB also supports

ORDER BY

clauses. This allows you to order the results returned by the query according

to one or more fields, in either ascending or descending order.
orientdb>

SELECT FROM Employee WHERE city='Rome' ORDER BY surname ASC, name ASC

The example queries the

Employee

class, it returns a listing of all employees in that class who live in Rome and it orders the results by

surname and name, in ascending order.

133

Basic SQL

GROUP BY
In the event that you need results of the query grouped together according to the values of certain fields, you can manage this using the
GROUP BY

clause.

orientdb>

SELECT SUM(salary) FROM Employee WHERE age < 40 GROUP BY job

In the example, you query the

Employee

class for the sum of the salaries of all employees under the age of forty, grouped by their job

types.

LIMIT
In the event that your query returns too many results, making it difficult to read or manage, you can use the

LIMIT

clause to reduce it

to the top most of the return values.
orientdb>

SELECT FROM Employee WHERE gender='male' LIMIT 20

In the example, you query the

Employee

class for a list of male employees. Given that there are likely to be a number of these, you

limit the return to the first twenty entries.

SKIP
When using the

LIMIT

clause with queries, you can only view the topmost of the return results. In the event that you would like to

view certain results further down the list, for instance the values from twenty to forty, you can paginate your results using the
keyword in the

LIMIT

SKIP

clause.

orientdb>

SELECT FROM Employee WHERE gender='male' LIMIT 20

orientdb>

SELECT FROM Employee WHERE gender='male' SKIP 20 LIMIT 20

orientdb>

SELECT FROM Employee WHERE gender='male' SKIP 40 LIMIT 20

The first query returns the first twenty results, the second returns the next twenty results, the third up to sixty. You can use these
queries to manage pages at the application layer.

INSERT
The

INSERT

statement adds new data to a class and cluster. OrientDB supports three forms of syntax used to insert new data into your

database.
The standard ANSI-92 syntax:
orientdb>

INSERT INTO

Employee(name, surname, gender)

VALUES('Jay', 'Miner', 'M')

The simplified ANSI-92 syntax:
orientdb>

INSERT INTO Employee SET name='Jay', surname='Miner', gender='M'

The JSON syntax:
orientdb>

INSERT INTO Employee CONTENT {name : 'Jay', surname : 'Miner',

gender : 'M'}

Each of these queries adds Jay M iner to the

Employee

class. You can choose whichever syntax that works best with your application.

134

Basic SQL

UPDATE
The

UPDATE

statement changes the values of existing data in a class and cluster. In OrientDB there are two forms of syntax used to

update data on your database.
The standard ANSI-92 syntax:
orientdb>

UPDATE Employee SET local=TRUE WHERE city='London'

The JSON syntax, used with the
orientdb>

MERGE

keyword, which merges the changes with the current record:

UPDATE Employee MERGE { local : TRUE } WHERE city='London'

Each of these statements updates the

Employee

class, changing the

local

property to

TRUE

when the employee is based in London.

DELETE
The

DELETE

statement removes existing values from your class and cluster. OrientDB supports the standard ANSI-92 compliant

syntax for these statements:
orientdb>

DELETE FROM Employee WHERE city <> 'London'

Here, entries are removed from the

Employee

class where the employee in question is not based in London.

S ee also:
The SQL Reference
The Console Command Reference

135

Users, Roles and Security

Users, Roles and Security

136

Distributed Architecture

Distributed Architecture

137

Tutorials

Tutorials
This Section includes all the Tutorials available in this M anual.

138

Working with Graphs

Working with Graphs
In graph databases, the database system graphs data into network-like structures consisting of vertices and edges. In the OrientDB
Graph model, the database represents data through the concept of a property graph, which defines a vertex as an entity linked with
other vertices and an edge, as an entity that links two vertices.
OrientDB ships with a generic vertex persistent class, called
new vertex using the
orientdb>

INSERT

command with

V

V

, as well as a class for edges, called

E

. As an example, you can create a

.

INSERT INTO V SET name='Jay'

Created record with RID #9:0

In effect, the Graph model database works on top of the underlying document model. But, in order to simplify this process, OrientDB
introduces a new set of commands for managing graphs from the console. Instead of
orientdb>

INSERT

, use

CREATE VERTEX

CREATE VERTEX V SET name='Jay'

Created vertex with RID #9:1

By using the graph commands over the standard SQL syntax, OrientDB ensures that your graphs remain consistent. For more
information on the particular commands, see the following pages:
CREATE VERTEX
DELETE VERTEX
CREATE EDGE
UPDATE EDGE
DELETE EDGE

Use Case: Social Network for Restaurant Patrons
While you have the option of working with vertexes and edges in your database as they are, you can also extend the standard
E

V

and

classes to suit the particular needs of your application. The advantages of this approach are,
It grants better understanding about the meaning of these entities.
It allows for optional constraints at the class level.
It improves performance through better partitioning of entities.
It allows for object-oriented inheritance among the graph elements.

For example, consider a social network based on restaurants. You need to start with a class for individual customers and another for the
restaurants they patronize. Create these classes to extend the
orientdb>

CREATE CLASS Person EXTENDS V

orientdb>

CREATE CLASS Restaurant EXTENDS V

V

class.

Doing this creates the schema for your social network. Now that the schema is ready, populate the graph with data.

139

Working with Graphs

orientdb>

CREATE VERTEX Person SET name='Luca'

Created record with RID #11:0

orientdb>

CREATE VERTEX Person SET name='Bill'

Created record with RID #11:1

orientdb>

CREATE VERTEX Person SET name='Jay'

Created record with RID #11:2

orientdb>

CREATE VERTEX Restaurant SET name='Dante', type='Pizza'

Created record with RID #12:0

orientdb>

CREATE VERTEX Restaurant SET name='Charlie', type='French'

Created record with RID #12:1

This adds three vertices to the
Restaurant

Person

class, representing individual users in the social network. It also adds two vertices to the

class, representing the restaurants that they patronize.

Creating Edges
For the moment, these vertices are independent of one another, tied together only by the classes to which they belong. That is, they are
not yet connected by edges. Before you can make these connections, you first need to create a class that extends
orientdb>

.

CREATE CLASS Eat EXTENDS E

This creates the class
Restaurant

E

Eat

, which extends the class

E

.

Eat

represents the relationship between the vertex

Person

and the vertex

.

When you create the edge from this class, note that the orientation of the vertices is important, because it gives the relationship its
meaning. For instance, creating an edge in the opposite direction, (from
as

Attendee

Restaurant

to

Person

), would call for a separate class, such

.

The user Luca eats at the pizza joint Dante. Create an edge that represents this connection:
orientdb>

CREATE EDGE Eat FROM ( SELECT FROM Person WHERE name='Luca' )

TO ( SELECT FROM Restaurant WHERE name='Dante' )

Creating Edges from Record ID
In the event that you know the Record ID of the vertices, you can connect them directly with a shorter and faster command. For
example, the person Bill also eats at the restaurant Dante and the person Jay eats at the restaurant Charlie. Create edges in the class
Eat

to represent these connections.

orientdb>

CREATE EDGE Eat FROM #11:1 TO #12:0

orientdb>

CREATE EDGE Eat FROM #11:2 TO #12:1

140

Working with Graphs

Querying Graphs
In the above example you created and populated a small graph of a social network of individual users and the restaurants at which they
eat. You can now begin to experiment with queries on a graph database.
To cross edges, you can use special graph functions, such as:
To retrieve the adjacent outgoing vertices

OUT()
IN()

To retrieve the adjacent incoming vertices
To retrieve the adjacent incoming and outgoing vertices

BOTH()

For example, to know all of the people who eat in the restaurant Dante, which has a Record ID of
that restaurant and traverse the incoming edges to discover which entries in the
orientdb>

Person

#12:0

, you can access the record for

class connect to it.

SELECT IN() FROM Restaurant WHERE name='Dante'

-------+----------------+
@RID

| in

|

-------+----------------+
#-2:1 | [#11:0, #11:1] |
-------+----------------+

This query displays the record ID's from the
EXPAND()

Person

class that connect to the restaurant Dante. In cases such as this, you can use the

special function to transform the vertex collection in the result-set by expanding it.

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

|

-------+-------------+-------------+---------+

Creating Edge to Connect Users
Your application at this point shows connections between individual users and the restaurants they patronize. While this is interesting,
it does not yet function as a social network. To do so, you need to establish edges that connect the users to one another.
To begin, as before, create a new class that extends
orientdb>

E

:

CREATE CLASS Friend EXTENDS E

The users Luca and Jay are friends. They have Record ID's of
orientdb>

In the

Friend

#11:0

and

#11:2

. Create an edge that connects them.

CREATE EDGE Friend FROM #11:0 TO #11:2

relationship, orientation is not important. That is, if Luca is a friend of Jay's then Jay is a friend of Luca's. Therefore,

you should use the

BOTH()

function.

141

Working with Graphs

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

|

-------+-------------+-------------+---------+-----------+

Here, the
the

Eat

BOTH()

function takes the edge class

Friend

as an argument, crossing only relationships of the Friend kind, (that is, it skips

class, at this time). Note in the result-set that the relationship with Luca, with a Record ID of

#11:0

in the

in_

field.

You can also now view all the restaurants patronized by friends of 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

|

-------+-------------+-------------+-------------+--------+

Lightweight Edges
In version 1.4.x, OrientDB begins to manage some edges as Lightweight Edges. Lightweight Edges do not have Record ID's, but are
physically stored as links within vertices. Note that OrientDB only uses a Lightweight Edge only when the edge has no properties,
otherwise it uses the standard Edge.
From the logic point of view, Lightweight Edges are Edges in all effects, so that all graph functions work with them. This is to improve
performance and reduce disk space.
Because Lightweight Edges don't exist as separate records in the database, some queries won't work as expected. For instance,
orientdb>

SELECT FROM E

For most cases, an edge is used connecting vertices, so this query would not cause any problems in particular. But, it would not return
Lightweight Edges in the result-set. In the event that you need to query edges directly, including those with no properties, disable the
Lightweight Edge feature.
To disable the Lightweight Edge feature, execute the following command.
orientdb>

ALTER DATABASE CUSTOM useLightweightEdges=FALSE

You only need to execute this command once. OrientDB now generates new edges as the standard Edge, rather than the Lightweight
Edge. Note that this does not affect existing edges.
For troubleshooting information on Lightweight Edges, see Why I can't see all the edges. For more information in the Graph model in
OrientDB, see Graph API.

142

Using Schema with Graphs

Using Schema with Graphs
OrientDB, through the Graph API, offers a number of features above and beyond the traditional Graph Databases given that it supports
concepts drawn from both the Document Database and the Object Oriented worlds. For instance, consider the power of graphs, when
used in conjunction with schemas and constraints.

Use Case: Car Database
For this example, consider a graph database that maps the relationship between individual users and their cars. First, create the graph
schema for the

Person

and

Car

vertex classes, as well as the

orientdb>

CREATE CLASS Person EXTENDS V

orientdb>

CREATE CLASS Car EXTENDS V

orientdb>

CREATE CLASS Owns EXTENDS E

Owns

edge class to connect the two:

These commands lay out the schema for your graph database. That is, they define two vertex classes and an edge class to indicate the
relationship between the two. With that, you can begin to populate the database with vertices and edges.
orientdb>

CREATE VERTEX Person SET name = 'Luca'

Created vertex 'Person#11:0{name:Luca} v1' in 0,012000 sec(s).

orientdb>

CREATE VERTEX Car SET name = 'Ferrari Modena'

Created vertex 'Car#12:0{name:Ferrari Modena} v1' in 0,001000 sec(s).

orientdb>

CREATE EDGE Owns FROM ( SELECT FROM Person ) TO ( SELECT FROM Car )

Created edge '[e[#11:0->#12:0][#11:0-Owns->#12:0]]' in 0,005000 sec(s).

Querying the Car Database
In the above section, you create a car database and populated it with vertices and edges to map out the relationship between drivers and
their cars. Now you can begin to query this database, showing what those connections are. For example, what is Luca's car? You can find
out by traversing from the vertex Luca to the outgoing vertices following the
orientdb>

Owns

relationship.

SELECT name FROM ( SELECT EXPAND( OUT('Owns') ) FROM Person

WHERE name='Luca' )

----+-------+-----------------+
#

| @RID

| name

|

----+-------+-----------------+
0

| #-2:1 | Ferrari Modena

|

----+-------+-----------------+

As you can see, the query returns that Luca owns a Ferrari M odena. Now consider expanding your database to track where each person
lives.

143

Using Schema with Graphs

Adding a Location Vertex
Consider a situation, in which you might want to keep track of the countries in which each person lives. In practice, there are a number
of reasons why you might want to do this, for instance, for the purposes of promotional material or in a larger database to analyze the
connections to see how residence affects car ownership.
To begin, create a vertex class for the country, in which the person lives and an edge class that connects the individual to the place.
orientdb>

CREATE CLASS Country EXTENDS V

orientdb>

CREATE CLASS Lives EXTENDS E

This creates the schema for the feature you're adding to the cars database. The vertex class
people live and the edge class

Lives

to connect individuals in the vertex class

Person

Country

recording countries in which

to entries in

Country

.

With the schema laid out, create a vertex for the United Kingdom and connect it to the person Luca.
orientdb>

CREATE VERTEX Country SET name='UK'

Created vertex 'Country#14:0{name:UK} v1' in 0,004000 sec(s).

orientdb>

CREATE EDGE Lives FROM ( SELECT FROM Person ) TO ( SELECT FROM Country

Created edge '[e[#11:0->#14:0][#11:0-Lives->#14:0]]' in 0,006000 sec(s).

The second command creates an edge connecting the person Luca to the country United Kingdom. Now that your cars database is
defined and populated, you can query it, such as a search that shows the countries where there are users that own a Ferrari.
orientdb>

SELECT name FROM ( SELECT EXPAND( IN('Owns').OUT('Lives') )

FROM Car WHERE name LIKE '%Ferrari%' )

---+-------+--------+
# | @RID

| name

|

---+-------+--------+
0 | #-2:1 | UK

|

---+-------+--------+

Using in and out Constraints on Edges
In the above sections, you modeled the graph using a schema without any constraints, but you might find it useful to use some. For
instance, it would be good to require that an

Owns

relationship only exist between the vertex

orientdb>

CREATE PROPERTY Owns.out LINK Person

orientdb>

CREATE PROPERTY Owns.in LINK Car

These commands link outgoing vertices of the

Person

class to incoming vertices of the

Car

Person

and the vertex

Car

.

class. That is, it configures your database

so that a user can own a car, but a car cannot own a user.

Using MANDATORY Constraints on Edges
By default, when OrientDB creates an edge that lacks properties, it creates it as a Lightweight Edge. That is, it creates an edge that has
no physical record in the database. Using the

MANDATORY

setting, you can stop this behavior, forcing it to create the standard Edge,

without outright disabling Lightweight Edges.

144

Using Schema with Graphs

orientdb>

ALTER PROPERTY Owns.out MANDATORY TRUE

orientdb>

ALTER PROPERTY Owns.in MANDATORY TRUE

Using UNIQUE with Edges
For the sake of simplicity, consider a case where you want to limit the way people are connected to cars to where the user can only
match to the car once. That is, if Luca owns a Ferrari M odena, you might prefer not to have a double entry for that car in the event that
he buys a new one a few years later. This is particularly important given that our database covers make and model, but not year.
To manage this, you need to define a
orientdb>

UNIQUE

index against both the out and in properties.

CREATE INDEX UniqueOwns ON Owns(out,in) UNIQUE

Created index successfully with 0 entries in 0,023000 sec(s).

The index returns tells us that no entries are indexed. You have already created the

Onws

relationship between Luca and the Ferrari

M odena. In that case, however, OrientDB had created a Lightweight Edge before you set the rule to force the creation of documents for
Owns

instances. To fix this, you need to drop and recreate the edge.

orientdb>

DELETE EDGE FROM #11:0 TO #12:0

orientdb>

CREATE EDGE Owns FROM ( SELECT FROM Person ) TO ( SELECT FROM Car )

To confirm that this was successful, run a query to check that a record was created:
orientdb>

SELECT FROM Owns

---+-------+-------+--------+
# | @RID

| out

| in

|

---+-------+-------+--------+
0 | #13:0 | #11:0 | #12:0

|

---+-------+-------+--------+

This shows that a record was indeed created. To confirm that the constraints work, attempt to create an edge in

Owns

that connects

Luca to the United Kingdom.
orientdb>

CREATE EDGE Owns FROM ( SELECT FROM Person ) TO ( SELECT FROM Country )

Error: com.orientechnologies.orient.core.exception.OCommandExecutionException:
Error on execution of command: sql.create edge Owns from (select from Person)...
Error: com.orientechnologies.orient.core.exception.OValidationException: The
field 'Owns.in' has been declared as LINK of type 'Car' but the value is the
document #14:0 of class 'Country'

This shows that the constraints effectively blocked the creation, generating a set of errors to explain why it was blocked.
You now have a typed graph with constraints. For more information, see Graph Schema.

145

Setup a Distributed Database

Setting up a Distributed Graph Database
In addition to the standard deployment architecture, where it runs as a single, standalone database instance, you can also deploy
OrientDB using Distributed Architecutre. In this environment, it shares the database across multiple server instances.

Launching Distributed Server Cluster
There are two ways to share a database across multiple server nodes:
Prior to startup, copy the specific database directory, under

to all servers.

$ORIENTDB_HOME/database

Keep the database on the first running server node, then start every other server node. Under the default configurations, OrientDB
automatically shares the database with the new servers that join.
This tutorial assumes that you want to start a distributed database using the second method.
NOTE: When you run in distributed mode, OrientDB needs more RAM. The minimum is 2GB of heap, but we suggest to use at least 4GB
of heap memory. To change the heap modify the Java memory settings in the file

bin/dserver.sh

(or dserver.bat on Windows).

Starting the First Server Node
Unlike the standard standalone deployment of OrientDB, there is a different script that you need to use when launching a distributed
server instance. Instead of
find it in the
$

bin

server.sh

, you use

dserver.sh

. In the case of Windows, use

dserver.bat

. Whichever you need, you can

of your installation directory.

./bin/dserver.sh

Bear in mind that OrientDB uses the same

orientdb-server-config.xml

configuration file, regardless of whether it's running as a server

or distributed server. For more information, see Distributed Configuration.
The first time you start OrientDB as a distributed server, it generates the following output:
+---------------------------------------------------------------+
|

WARNING: FIRST DISTRIBUTED RUN CONFIGURATION

|

+---------------------------------------------------------------+
| This is the first time that the server is running as

|

| distributed. Please type the name you want to assign to the

|

| current server node.

|

|

|

| To avoid this message set the environment variable or JVM

|

| setting ORIENTDB_NODE_NAME to the server node name to use.

|

+---------------------------------------------------------------+
Node name [BLANK=auto generate it]:

You need to give the node a name here. OrientDB stores it in the
your

orientdb-server-config.xml

nodeName

parameter of

OHazelcastPlugin

. It adds the variable to

configuration file.

Distributed Startup Process
When OrientDB starts as a distributed server instance, it loads all databases in the

database

directory and configures them to run in

distributed mode. For this reason, the first load, OrientDB copies the default distributed configuration, (that is, the
distributed-db-config.json

configuration file), into each database's directory, renaming it

distributed-config.json

default-

. On subsequent

starts, each database uses this file instead of the default configuration file. Since the shape of the cluster changes every time nodes join or
leave, the configuration is kept up to date by each distributed server instance.
For more information on working with the

default-distributed-db-config.json

configuration file, see Distributed Configuration.

Starting Additional Server Nodes
146

Setup a Distributed Database
When you have the first server node running, you can begin to start the other server nodes. Each server requires the same Hazelcast
credentials in order to join the same cluster. You can define these in the

hazelcast.xml

configuration file.

The fastest way to initialize multiple server nodes is to copy the OrientDB installation directory from the first node to each of the
subsequent nodes. For instance,
$

scp user@ip_address $ORIENTDB_HOME

This copies both the databases and their configuration files onto the new distributed server node.
Bear in mind, if you run multiple server instances on the same host, such as when testing, you need to change the port entry in
the

hazelcast.xml

configuration file.

For the other server nodes in the cluster, use the same

dserver.sh

command as you used in starting the first node. When the other

server nodes come online, they begin to establish network connectivity with each other. M onitoring the logs, you can see where they
establish connections from messages such as this:
WARN [node1384014656983] added new node id=Member [192.168.1.179]:2435 name=null
[OHazelcastPlugin]
INFO [192.168.1.179]:2434 [orientdb] Re-partitioning cluster data... Migration
queue size: 135 [PartitionService]
INFO [192.168.1.179]:2434 [orientdb] All migration tasks has been completed,
queues are empty. [PartitionService]
INFO [node1384014656983] added node configuration id=Member [192.168.1.179]:2435
name=node1384015873680, now 2 nodes are configured [OHazelcastPlugin]
INFO [node1384014656983] update configuration db=GratefulDeadConcerts
from=node1384015873680 [OHazelcastPlugin]
INFO updated distributed configuration for database: GratefulDeadConcerts:
---------{
"replication": true,
"autoDeploy": true,
"hotAlignment": true,
"resyncEvery": 15,
"clusters": {
"internal": {
"replication": false
},
"index": {
"replication": false
},
"*": {
"replication": true,
"readQuorum": 1,
"writeQuorum": 2,
"failureAvailableNodesLessQuorum": false,
"readYourWrites": true,
"partitioning":{
"strategy": "round-robin",
"default":0,
"partitions": ["","node1383734730415","node1384015873680"]("","node1383734730415","node1384015873680".md)
}
}
},
"version": 1
}

---------- [OHazelcastPlugin]
WARN [node1383734730415]->[node1384015873680] deploying database
GratefulDeadConcerts...[ODeployDatabaseTask]
WARN [node1383734730415]->[node1384015873680] sending the compressed database
GratefulDeadConcerts over the network, total 339,66Kb [ODeployDatabaseTask]

147

Setup a Distributed Database
In the example, two server nodes were started on the same machine. It has an IP address of 10.37.129.2, but is using OrientDB on two
different ports: 2434 and 2435, where the current is called

this

. The remainder of the log is relative to the distribution of the database

to the second server.
On the second server node output, OrientDB dumps messages like this:
WARN [node1384015873680]<-[node1383734730415] installing database
GratefulDeadConcerts in databases/GratefulDeadConcerts... [OHazelcastPlugin]
WARN [node1384015873680] installed database GratefulDeadConcerts in
databases/GratefulDeadConcerts, setting it online... [OHazelcastPlugin]
WARN [node1384015873680] database GratefulDeadConcerts is online [OHazelcastPlugin]
WARN [node1384015873680] updated node status to 'ONLINE' [OHazelcastPlugin]
INFO OrientDB Server v1.6.1-SNAPSHOT is active. [OServer]

What these messages mean is that the database
node1383734730415

GratefulDeadConcerts

was correctly installed from the first node, that is

through the network.

Migrating from standalone server to a cluster
If you have a standalone instance of OrientDB and you want to move to a cluster you should follow these steps:
Install OrientDB on all the servers of the cluster and configure it (according to the sections above)
Stop the standalone server
Copy the specific database directories under

$ORIENTDB_HOME/database

Start all the servers in the cluster using the script

dserver.sh

(or

to all the servers of the cluster

dserver.bat

if on Windows)

If the standalone server will be part of the cluster, you can use the existing installation of OrientDB; you don't need to copy the
database directories since they're already in place and you just have to start it before all the other servers with

dserver.sh

.

148

Working with Distributed Graphs

Working with Distributed Graphs
When OrientDB joins a distributed cluster, all clients connecting to the server node are constantly notified about this state. This ensures
that, in the event that server node fails, the clients can switch transparently to the next available server.
You can check this through the console. When OrientDB runs in a distributed configuration, the current cluster shape is visible through
the
$

INFO

command.

$ORIENTDB_HOME/bin/console.sh

OrientDB console v.1.6 www.orientechnologies.com
Type 'help' to display all the commands supported.
Installing extensions for GREMLIN language v.2.5.0-SNAPSHOT

orientdb>

CONNECT remote:localhost/GratefulDeadConcerts admin admin

Connecting to database [remote:localhost/GratefulDeadConcerts] with user 'admin'...OK

orientdb>

INFO

Current database: GratefulDeadConcerts (url=remote:localhost/GratefulDeadConcerts)

For reference purposes, the server nodes in the example have the following configurations. As you can see, it is a two node cluster
running a single server host. The first node listens on port

2481

while the second on port

2480

.

+---------+------+-----------------------------------------+-----+---------+--------------+--------------+----------------------+
|Name

|Status|Databases

|Conns|StartedOn|Binary

|HTTP

|UsedMemory

|
+---------+------+-----------------------------------------+-----+---------+--------------+--------------+----------------------+
|europe-0 |ONLINE|distributed-node-deadlock=ONLINE (MASTER)|5

|16:53:59 |127.0.0.1:2424|127.0.0.1:2480|269.32MB/3.56GB (7.40

%)|
|europe-1 |ONLINE|distributed-node-deadlock=ONLINE (MASTER)|4

|16:54:03 |127.0.0.1:2425|127.0.0.1:2481|268.89MB/3.56GB (7.38

%)|
+---------+------+-----------------------------------------+-----+---------+--------------+--------------+----------------------+

Testing Distributed Architecture
Once you have a distributed database up and running, you can begin to test its operations on a running environment. For example, begin
by creating a vertex, setting the
orientdb>

node

property to

1

.

CREATE VERTEX V SET node = 1

Created vertex 'V#9:815{node:1} v1' in 0,013000 sec(s).

From another console, connect to the second node and execute the following command:

149

Working with Distributed Graphs

orinetdb>

SELECT FROM V WHERE node = 1

----+--------+-------+
#

| @RID

| node

|

----+--------+-------+
0

| #9:815 | 1

|

----+--------+-------+
1 item(s) found. Query executed in 0.19 sec(s).

This shows that the vertex created on the first node has successfully replicated to the second node.

Logs in Distributed Architecture
From time to time server nodes go down. This does not necessarily relate to problems in OrientDB, (for instance, it could originate from
limitations in system resources).
To test this out, kill the first node. For example, assuming the first node has a process identifier, (that is, a PID), of

1254

on your

system, run the following command:
$

kill -9 1254

This command kills the process on PID
$

1254

. Now, check the log messages for the second node:

less orientdb.log

INFO [127.0.0.1]:2435 [orientdb] Removing Member [127.0.0.1]:2434
[ClusterService]
INFO [127.0.0.1]:2435 [orientdb]
Members [1] {
Member [127.0.0.1]:2435 this
}

[ClusterService]
WARN [europe-0] node removed id=Member [127.0.0.1]:2434
name=europe-1 [OHazelcastPlugin]
INFO [127.0.0.1]:2435 [orientdb] Partition balance is ok, no need to
re-partition cluster data...

[PartitionService]

What the logs show you is that the second node is now aware that it cannot reach the first node. You can further test this by running the
console connected to the first node..
orientdb>

SELECT FROM V LIMIT 2

WARN Caught I/O errors from /127.0.0.1:2425 (local
socket=0.0.0.0/0.0.0.0:51512), trying to reconnect (error:
java.io.IOException: Stream closed) [OStorageRemote]
WARN Connection re-acquired transparently after 30ms and 1 retries: no errors
will be thrown at application level [OStorageRemote]
---+------+----------------+--------+--------------+------+-----------------+----# | @RID | name

| song_type | performances | type | out_followed_by | ...

---+------+----------------+--------+--------------+------+-----------------+----1 | #9:1 | HEY BO DIDDLEY | cover

| 5

| song | [5]

| ...

2 | #9:2 | IM A MAN

| 1

| song | [2]

| ...

| cover

---+------+----------------+--------+--------------+------+-----------------+-----

150

Working with Distributed Graphs
This shows that the console auto-switched to the next available node. That is, it switched to the second node upon noticing that the first
was no longer functional. The warnings reports show what happened in a transparent way, so that the application doesn't need to
manage the issue.
From the console connected to the second node, create a new vertex.
orientdb>

CREATE VERTEX V SET node=2

Created vertex 'V#9:816{node:2} v1' in 0,014000 sec(s).

Given that the first node remains nonfunctional, OrientDB journals the operation. Once the first node comes back online, the second
node synchronizes the changes into it.
Restart the first node and check that it successfully auto-realigns. Reconnect the console to the first node and run the following
command:
orientdb>

SELECT FROM V WHERE node=2

---+--------+-------+
# | @RID

| node

|

---+--------+-------+
0 | #9:816 | 2

|

---+--------+-------+
1 item(s) found. Query executed in 0.209 sec(s).

This shows that the first node has realigned itself with the second node.
This process is repeatable with N server nodes, where every server is a master. There is no limit to the number of running servers. With
many servers spread across a slow network, you can tune the network timeouts to be more permissive and let a large, distributed cluster
of servers work properly.
For more information, Distributed Architecture.

151

Time Series

Time Series Use Case
M anaging records related to historical information is pretty common. When you have millions of records, indexes start show their
limitations, because the cost to find the records is O(logN). This is also the main reason why Relational DBM S are so slow with huge
databases.
So when you have millions of record the best way to scale up linearly is avoid using indexes at all or as much as you can. But how can
you retrieve records in a short time without indexes? Should OrientDB scan the entire database at every query? No. You should use the
Graph properties of OrientDB. Let's look at a simple example, where the domain are logs.
A typical log record has some information about the event and a date. Below is the Log record to use in our example. We're going to use
the JSON format to simplify reading:
{
"date" : 12293289328932,
"priority" : "critical",
"note" : "System reboot"
}

Now let's create a tree (that is a directed, non cyclic graph) to group the Log records based on the granularity we need. Example:
Year -> month (map) -> Month -> day (map) -> Day -> hour

(map) -> Hour

Where Year, M onth, Day and Hour are vertex classes. Each Vertex links the other Vertices of smaller type. The links should be handled
using a M ap to make easier the writing of queries.
Create the classes:
CREATE CLASS Year
CREATE CLASS Month
CREATE CLASS Day
CREATE CLASS Hour
CREATE PROPERTY Year.month LINKMAP Month
CREATE PROPERTY Month.day LINKMAP Day
CREATE PROPERTY Day.hour LINKMAP Hour

Example to retrieve the vertex relative to the date M arch 2012, 20th at 10am (2012/03/20 10:00:00):
SELECT month[3].day[20].hour[10].logs FROM Year WHERE year = "2012"

If you need more granularity than the Hour you can go ahead until the Time unit you need:
Hour -> minute (map) -> Minute -> second (map) -> Second

Now connect the record to the right Calendar vertex. If the usual way to retrieve Log records is by hour you could link the Log records
in the Hour. Example:
Year -> month (map) -> Month -> day (map) -> Day -> hour

(map) -> Hour -> log (set) -> Log

The "log" property connects the Time Unit to the Log records. So to retrieve all the log of M arch 2012, 20th at 10am:
SELECT expand( month[3].day[20].hour[10].logs ) FROM Year WHERE year = "2012"

That could be used as starting point to retrieve only a sub-set of logs that satisfy certain rules. Example:

152

Time Series
SELECT FROM (
SELECT expand( month[3].day[20].hour[10].logs ) FROM Year WHERE year = "2012"
) WHERE priority = 'critical'

That retrieves all the CRITICAL logs of M arch 2012, 20th at 10am.

Join multiple hours
If you need multiple hours/days/months as result set you can use the UNION function to create a unique result set:
SELECT expand( records ) from (
SELECT union( month[3].day[20].hour[10].logs, month[3].day[20].hour[11].logs ) AS records
FROM Year WHERE year = "2012"
)

In this example we create a union between the 10th and 11th hours. But what about extracting all the hours of a day without writing a
huge query? The shortest way is using the Traverse. Below the Traverse to get all the hours of one day:
TRAVERSE hour FROM (
SELECT expand( month[3].day[20] ) FROM Year WHERE year = "2012"
)

So putting all together this query will extract all the logs of all the hours in a day:
SELECT expand( logs ) FROM (
SELECT union( logs ) AS logs FROM (
TRAVERSE hour FROM (
SELECT expand( month[3].day[20] ) FROM Year WHERE year = "2012"
)
)
)

Aggregate
Once you built up a Calendar in form of a Graph you can use it to store aggregated values and link them to the right Time Unit.
Example: store all the winning ticket of Online Games. The record structure in our example is:
{
"date" : 12293289328932,
"win" : 10.34,
"machine" : "AKDJKD7673JJSH",
}

You can link this record to the closest Time Unit like in the example above, but you could sum all the records in the same Day and link it
to the Day vertex. Example:
Create a new class to store the aggregated daily records:
CREATE CLASS DailyLog

Create the new record from an aggregation of the hour:
INSERT INTO DailyLog
SET win = (
SELECT SUM(win) AS win FROM Hour WHERE date BETWEEN '2012-03-20 10:00:00' AND '2012-03-20 11:00:00'
)

Link it in the Calendar graph assuming the previous command returned #23:45 as the RecordId of the brand new DailyLog record:

153

Time Series
UPDATE (
SELECT expand( month[3].day[20] ) FROM Year WHERE year = "2012"
) ADD logs = #23:45

154

Chat

Chat Use Case
OrientDB allows modeling of rich and complex domains. If you want to develop a chat based application, you can use whatever you
want to create the relationships between User and Room.
We suggest avoiding using Edges or Vertices connected with edges for messages. The best way is using the document API by creating
one class per chat room, with no index, to have super fast access to last X messages. In facts, OrientDB stores new records in append
only, and the @rid is auto generated as incrementing.
The 2 most common use cases in a chat are:
writing a message in a chat room
load last page of messages in a chat room

Create the initial schema
In order to work with the chat rooms, the rule of the thumb is creating a base abstract class ("ChatRoom") and then let to the concrete
classes to represent individual ChatRooms.

Create the base ChatRoom class
create class ChatRoom
alter class ChatRoom abstract true
create property ChatRoom.date datetime
create property ChatRoom.text string
create property ChatRoom.user LINK OUser

Create a new ChatRoom
create class ItalianRestaurant extends ChatRoom

Class "ItalianRestaurant" will extend all the properties from ChatRoom.
Why creating a base class? Because you could always execute polymorphic queries that are cross-chatrooms, like get all the message
from user "Luca":
select from ChatRoom where user.name = 'Luca'

Create a new message in the Chat Room
To create a new message in the chat room you can use this code:
public ODocument addMessage(String chatRoom, String message, OUser user) {
ODocument msg = new ODocument(chatRoom);
msg.field( "date", new Date() );
msg.field( "text", message );
msg.field( "user", user );
msg.save();
return msg;
}

Example:
addMessage("ItalianRestaurant", "Have you ever been at Ponza island?", database.getUser());

155

Chat

Retrieve last messages
You can easily fetch pages of messages ordered by date in descending order, by using the OrientDB's

@rid

. Example:

select from ItalianRestaurant order by @rid desc skip 0 limit 50

You could write a generic method to access to a page of messages, like this:
public Iterable loadMessages(String chatRoom, fromLast, pageSize) {
return graph.getRawGraph().command("select from " + chatRoom + " order by @rid desc skip " + fromLast + " limit " + pageSize
).execute();
}

Loading the 2nd (last) page from chat "ItalianRestaurant", would become this query (with pageSize = 50):
select from ItalianRestaurant order by @rid desc skip 50 limit 50

This is super fast and O(1) even with million of messages.

Limitations
Since OrientDB can handle only 32k clusters, you could have maximum 32k chat rooms. Unless you want to rewrite the entire
FreeNode, 32k chat rooms will be more than enough for most of the cases.
However, if you need more than 32k chat rooms, the suggested solution is still using this approach, but with multiple databases (even
on the same server, because one OrientDB Server instance can handle thousands of databases concurrently).
In this case you could use one database to handle all the metadata, like the following classes:
ChatRoom, containing all the chatrooms, and the database where are stored. Example:

{ "@class": "ChatRoom", "description":

"OrientDB public channel", "databaseName", "db1", "clusterName": "orientdb" }

User, containing all the information about accounts with the edges to the ChatRoom vertices where they are subscribed
OrientDB cannot handle cross-database links, so when you want to know the message's author, you have to look up into the
"M etadata" database by @RID (that is O(1)).

156

Key Value

Key Value Use Case
OrientDB can also be used as a Key Value DBM S by using the super fast Indexes. You can have as many Indexes as you need.

HTTP
OrientDB RESTful HTTP protocol allows to talk with a OrientDB Server instance using the HTTP protocol and JSON. OrientDB
supports also a highly optimized Binary protocol for superior performances.

Operations
To interact against OrientDB indexes use the four methods of the HTTP protocol in REST fashion:
PUT, to create or modify an entry in the database
GET, to retrieve an entry from the database. It's idempotent that means no changes to the database happen. Remember that in IE6
the URL can be maximum of 2,083 characters. Other browsers supports longer URLs, but if you want to stay compatible with all
limit to 2,083 characters
DELETE, to delete an entry from the database

Create an entry
To create a new entry in the database use the Index-PUT API.
Syntax:

http://:[]/index//

Example:
HTTP PUT:

http://localhost:2480/index/customers/jay

{
"name" : "Jay",
"surname" : "Miner"
}

HTTP Response 204 is returned.

Retrieve an entry
To retrieve an entry from the database use the Index-GET API.
Syntax:

http://:[]/index//

Example:
HTTP GET:

http://localhost:2480/index/customers/jay

HTTP Response 200 is returned with this JSON as payload:
{
"name" : "Jay",
"surname" : "Miner"
}

Remove an entry

157

Key Value
To remove an entry from the database use the Index-DELETE API.
Syntax:

http://:[]/index//

Example:
HTTP DELETE:

http://localhost:2480/index/customers/jay

HTTP Response 200 is returned

Step-by-Step tutorial
Before to start assure you've a OrientDB server up and running. In this example we'll use curl considering the connection to localhost to
the default HTTP post 2480. The default "admin" user is used.

Create a new index
To use OrientDB as a Key/Value store we need a brand new manual index, let's call it "mainbucket". We're going to create it as UNIQUE
because keys cannot be duplicated. If you can have multiple keys consider:
creating the index as NOTUNIQUE
leave it as UNIQUE but as value handle array of documents
Create the new manual unique index "mainbucket":
> curl --basic -u admin:admin localhost:2480/command/demo/sql -d "create index mainbucket UNIQUE"

Response:
{ "result" : [
{ "@type" : "d" , "@version" : 0, "value" : 0, "@fieldTypes" : "value=l" }
]
}

Store the first entry
Below we're going to insert the first entry by using the HTTP PUT method passing "jay" as key in the URL and as value the entire
document in form of JSON:
> curl --basic -u admin:admin -X PUT localhost:2480/index/demo/mainbucket/jay -d "{'name':'Jay','surname':'Miner'}"

Response:
Key 'jay' correctly inserted into the index mainbucket.

Retrieve the entry just inserted
Below we're going to retrieve the entry we just entered by using the HTTP GET method passing "jay" as key in the URL:
> curl --basic -u admin:admin localhost:2480/index/demo/mainbucket/jay

Response:

158

Key Value
[{
"@type" : "d" , "@rid" : "#3:477" , "@version" : 0,
"name" : "Jay",
"surname" : "Miner"
}]

Note that an array is always returned in case multiple records are associated to the same key (if NOTUNIQUE index is used). Look also
at the document has been created with RID #3:477. You can load it directly if you know the RID. Remember to remove the # character.
Example:
> curl --basic -u admin:admin localhost:2480/document/demo/3:477

Response:
{
"@type" : "d" , "@rid" : "#3:477" , "@version" : 0,
"name" : "Jay",
"surname" : "Miner"
}

Drop an index
Once finished drop the index "mainbucket" created for the example:
> curl --basic -u admin:admin localhost:2480/command/demo/sql -d "drop index mainbucket"

Response:
{ "result" : [
{ "@type" : "d" , "@version" : 0, "value" : 0, "@fieldTypes" : "value=l" }
]
}

159

Queue system

Distributed queues use case
Implementing a persistent, distributed and transactional queue system using OrientDB is possible and easy. Besides the fact you don't
need a specific API accomplish a queue, there are multiple approaches you can follow depending by your needs. The easiest way is
using OrientDB SQL, so this works with any driver.
Create the queue class first:
create class queue

You could have one class per queue. Example of push operation:
insert into queue set text = "this is the first message", date = date()

Since OrientDB by default keeps the order of creation of records, a simple delete from the queue class with limit = 1 gives to you the
perfect pop:
delete from queue return before limit 1

The "return before" allows you to have the deleted record content. If you need to peek the queue, you can just use the select:
select from queue limit 1

That's it. Your queue will be persistent, if you want transactional and running in cluster distributed.

160

Import Tutorials

Import Tutorials
This section includes some import-to-OrientDB tutorials.

161

Import Tutorials

Tutorial: Importing the Open Beer Database into OrientDB

In this tutorial we will use the OrientDB's ETL module to import, as a graph, the Open Beer Database.
Note: You can access directly the converted database, result of this ETL tutorial, in the following ways:
S tudio: in the login page press the "Cloud" button, put server's credential and press the download button from the "OpenBeer"
row;
Direct Download: download the database from http://orientdb.com/public-databases/OpenBeer.zip and unzip it in a OpenBeer
folder inside OrientDB's server "databases" directory.

The Open Beer Database
The Open Beer Database can be downloaded in CSV format from https://openbeerdb.com/. The following image shows its relational
model:

Preliminary Steps
First, please create a new folder somewhere in your hard drive, and move into it. For this test we will assume

/temp/openbeer

:

$ mkdir /temp/openbeer
$ cd /temp/openbeer

162

Import Tutorials

Download the Open Beer Database in CSV format
Download the Open Beer Database in CSV format and extract the archive:
$ curl http://openbeerdb.com/files/openbeerdb_csv.zip > openbeerdb_csv.zip
$ unzip openbeerdb_csv.zip

The archive consists of the following files:
beers.csv:

contains the beer records

breweries.csv:

contains the breweries records

breweries_geocode.csv
categories.csv
styles.csv

: contains the geocodes of the breweries. This file is not used in this Tutorial

: contains the beer categories

: contains the beer styles

Install OrientDB
Download and install OrientDB:
$ wget http://orientdb.com/download.php?file=orientdb-community-importers-3.0.0RC1.tar.gz&utm_source=Labs&utm_medium=link&utm_
campaign=300 -O orientdb-community-3.0.0RC1.tar.gz
$ tar xvf orientdb-community-3.0.0RC1.tar.gz

For more information on how to install OrientDB, please refer to the Installation section.

Graph Data Model
Before starting the ETL process it's important to understand how the Open Beer Database can be modeled as a graph.
The relational model of the Open Beer Database can be easily converted to a graph model, as shown below:

The model above consists of the following nodes (or vertices) and relationships (or edges):
Nodes: Beer, Category, Style, Brewery;
Relationships: HasCategory, HasStyle, HasBrewery.
For more informations on the Graph M odel in OrientDB, please refer to the Graph M odel section.

163

Import Tutorials

ETL Process
The ETL module for OrientDB provides support for moving data to and from OrientDB databases using Extract, Transform and Load
processes.
The ETL module consists of a script,

oetl.sh

, that takes in input a single JSON configuration file.

For more information on the ETL module, please refer to the ETL section.

Import Beer Categories
The following are the first two lines of the

categories.csv

file:

"id","cat_name","last_mod"
"1","British Ale","2010-10-24 13:50:10"

In order to import this file in OrientDB, we have to create the following file as

categories.json

:

{
"source": { "file": { "path": "/temp/openbeer/openbeerdb_csv/categories.csv" } },
"extractor": { "csv": {} },
"transformers": [
{ "vertex": { "class": "Category" } }
],
"loader": {
"orientdb": {
"dbURL": "plocal:../databases/openbeerdb",
"dbType": "graph",
"classes": [
{"name": "Category", "extends": "V"}
], "indexes": [
{"class":"Category", "fields":["id:integer"], "type":"UNIQUE" }
]
}
}
}

To import it into OrientDB, please move into the "bin" directory of the OrientDB distribution:
$ cd orientdb-community-2.2.8/bin

and run OrientDB ETL:
$ ./oetl.sh /temp/openbeer/categories.json
OrientDB etl v.2.0.9 (build @BUILD@) www.orientechnologies.com
BEGIN ETL PROCESSOR
END ETL PROCESSOR
+ extracted 12 rows (0 rows/sec) - 12 rows -> loaded 11 vertices (0 vertices/sec) Total time: 77ms [0 warnings, 0 errors]

Import Beer Styles
Now let's import the Beer Styles. These are the first two lines of the

styles.csv

file:

"id","cat_id","style_name","last_mod"
"1","1","Classic English-Style Pale Ale","2010-10-24 13:53:31"

In this case we will correlate the Style with the Category created earlier.
This is the

styles.json

to use with OrientDB ETL for the next step:

164

Import Tutorials
{
"source": { "file": { "path": "/temp/openbeer/openbeerdb_csv/styles.csv" } },
"extractor": { "csv": {} },
"transformers": [
{ "vertex": { "class": "Style" } },
{ "edge": { "class": "HasCategory",

"joinFieldName": "cat_id", "lookup": "Category.id" } }

],
"loader": {
"orientdb": {
"dbURL": "plocal:../databases/openbeerdb",
"dbType": "graph",
"classes": [
{"name": "Style", "extends": "V"},
{"name": "HasCategory", "extends": "E"}
], "indexes": [
{"class":"Style", "fields":["id:integer"], "type":"UNIQUE" }
]
}
}
}

Now, to import the styles, please execute the following command:
$ ./oetl.sh /temp/openbeer/styles.json
OrientDB etl v.2.0.9 (build @BUILD@) www.orientechnologies.com
BEGIN ETL PROCESSOR
END ETL PROCESSOR
+ extracted 142 rows (0 rows/sec) - 142 rows -> loaded 141 vertices (0 vertices/sec) Total time: 498ms [0 warnings, 0 errors]

Import Breweries
Now it's time for the Breweries. These are the first two lines of the

breweries.csv

file:

"id","name","address1","address2","city","state","code","country","phone","website","filepath","descript","last_mod"
"1","(512) Brewing Company","407 Radam, F200",,"Austin","Texas","78745","United States","512.707.2337","http://512brewing.com/
",,"(512) Brewing Company is a microbrewery located in the heart of Austin that brews for the community using as many local, d
omestic and organic ingredients as possible.","2010-07-22 20:00:20"

Breweries have no outgoing relations with other entities, so this is a plain import similar to the one we did for the categories.
This is the

breweries.json

to use with OrientDB ETL for the next step:

{
"source": { "file": { "path": "/temp/openbeer/openbeerdb_csv/breweries.csv" } },
"extractor": { "csv": {} },
"transformers": [
{ "vertex": { "class": "Brewery" } }
],
"loader": {
"orientdb": {
"dbURL": "plocal:../databases/openbeerdb",
"dbType": "graph",
"classes": [
{"name": "Brewery", "extends": "V"}
], "indexes": [
{"class":"Brewery", "fields":["id:integer"], "type":"UNIQUE" }
]
}
}
}

Run the import for breweries:

165

Import Tutorials
$ ./oetl.sh /temp/openbeer/breweries.json
OrientDB etl v.2.0.9 (build @BUILD@) www.orientechnologies.com
BEGIN ETL PROCESSOR
END ETL PROCESSOR
+ extracted 1.395 rows (0 rows/sec) - 1.395 rows -> loaded 1.394 vertices (0 vertices/sec) Total time: 830ms [0 warnings, 0 er
rors]

Import Beers
Now it's time for the last and most important file: the Beers! These are the first two lines of the

beers.csv

file:

"id","brewery_id","name","cat_id","style_id","abv","ibu","srm","upc","filepath","descript","last_mod",,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,
"1","812","Hocus Pocus","11","116","4.5","0","0","0",,"Our take on a classic summer ale.
aze.

A toast to weeds, rays, and summer h

A light, crisp ale for mowing lawns, hitting lazy fly balls, and communing with nature, Hocus Pocus is offered up as a s

ummer sacrifice to clodless days.

As you can see each beer is connected to other entities through the following fields:
brewery_id
cat_id

style_id

This is the

-> Brewery

-> Category
-> S tyle

beers.json

to use with OrientDB ETL for the next step:

{
"config" : { "haltOnError": false },
"source": { "file": { "path": "/temp/openbeer/openbeerdb_csv/beers.csv" } },
"extractor": { "csv": { "columns": ["id","brewery_id","name","cat_id","style_id","abv","ibu","srm","upc","filepath","descrip
t","last_mod"],
"columnsOnFirstLine": true } },
"transformers": [
{ "vertex": { "class": "Beer" } },
{ "edge": { "class": "HasCategory",

"joinFieldName": "cat_id", "lookup": "Category.id" } },

{ "edge": { "class": "HasBrewery",

"joinFieldName": "brewery_id", "lookup": "Brewery.id" } },

{ "edge": { "class": "HasStyle",

"joinFieldName": "style_id", "lookup": "Style.id" } }

],
"loader": {
"orientdb": {
"dbURL": "plocal:../databases/openbeerdb",
"dbType": "graph",
"classes": [
{"name": "Beer", "extends": "V"},
{"name": "HasCategory", "extends": "E"},
{"name": "HasStyle", "extends": "E"},
{"name": "HasBrewery", "extends": "E"}
], "indexes": [
{"class":"Beer", "fields":["id:integer"], "type":"UNIQUE" }
]
}
}
}

Run the final import for beers:
$ ./oetl.sh /temp/openbeer/beers.json
OrientDB etl v.2.0.9 (build @BUILD@) www.orientechnologies.com
BEGIN ETL PROCESSOR
...
+ extracted 5.862 rows (1.041 rows/sec) - 5.862 rows -> loaded 4.332 vertices (929 vertices/sec) Total time: 10801ms [0 warnin
gs, 27 errors]
END ETL PROCESSOR

166

Import Tutorials
Note: the 27 errors are due to the 27 wrong content lines that have no id.

Some Queries and Visualizations
Now that the database has been imported we can execute some queries and create some visualizations.
The following are some ways we can use to access the newly imported

OpenBeer

database:

Console
Gremlin Console
Studio
APIs & Drivers
some external tools, like Gephy
some external visualization libraries for graph rendering
If we want to query all Category vertices we can execute the following query:
SELECT * FROM Category

The following is the visualization we can create using the Studio's Graph Editor:

If we want to find all nodes directly connected to a specific beer (e.g. the beer Petrus Dubbel Bruin Ale) with either an incoming or
outgoing relationship, we can use a query like the following:
SELECT EXPAND( BOTH() ) FROM Beer WHERE name = 'Petrus Dubbel Bruin Ale'

Alternatively, we can use the M ATCH syntax:
MATCH {class: Beer, where: (name = 'Petrus Dubbel Bruin Ale')}--{as: n} RETURN $pathelements

If we execute the first query in the Browse tab of Studio we get the following result, from where we can see that there are three nodes
connected to this beer, having @rid 11:4, 14:262 and 12:59:

167

Import Tutorials

We can send the result of this

SELECT

query to the Graph Editor by clicking the icon "Send to Graph", or create a new visualization

directly from the Graph Editor.
The following is the visualization of the

MATCH

query above, executed directly on the Graph Editor:

The same resultset can be visualized using an external graph library. For instance, the following graph has been obtained using the library
vis.js where the input visjs dataset has been created with a java program created using the OrientDB's Java Graph API:

168

Import Tutorials

We can also query bigger portions of the graph. For example, to query all beer Category nodes and for each of them all the connected
Style nodes, we can use a M ATCH query like the following:
MATCH
{class: Category, as: category}-HasCategory-{class: Style, as: style}
RETURN $elements

The following is the visualization of the

MATCH

query above in the Graph Editor:

while the following is a visualization created for the same recordset using the library vis.js:

169

Import Tutorials

170

Import Tutorials

Tutorial: Importing the northwind Database from Neo4j
In this tutorial we will use the Neo4j to OrientDB Importer to import the Neo4j northwind example database into OrientDB.
For general information on the possible Neo4j to OrientDB migration strategies, please refer to the Import from Neo4j section.
Neo4j and Cypher are registered trademark of Neo Technology, Inc.

Preparing for the migration
Please download and install OrientDB:
$ wget http://orientdb.com/download.php?file=orientdb-community-tp2-3.0.0RC1.tar.gz&utm_source=Labs&utm_medium=link&utm_campai
gn=300 -O orientdb-community-tp2-3.0.0RC1.tar.gz
$ tar xvf orientdb-community-tp2-3.0.0RC1.tar.gz

Download and install the Neo4j to OrientDB Importer:
$ wget http://central.maven.org/maven2/com/orientechnologies/orientdb-neo4j-importer/3.0.0RC1/orientdb-neo4j-importer-3.0.0RC1
.tar.gz
$ tar xfv orientdb-neo4j-importer-3.0.0RC1.tar.gz -C orientdb-community-3.0.0RC1 --strip-components=1

For further information on the OrientDB's installation, please refer to this section.
For further information on the Neo4j to OrientDB Importer installation, please refer to this section.

Starting the migration
Assuming that:
/home/santo/neo4j/neo4j-community-3.0.7/lib
/home/santo/data/graph.db_northwind

is the full path to the directory that includes the Neo4j's libraries

is the full path to the directory that contains the Neo4j's northwind database

/home/santo/orientdb/orientdb-community-2.2.12/databases/northwind_import

is the full path to the directory where you would

like to migrate the northwind database
that no Neo4j and OrientDB servers are running on those directories
you can import the northwind database with a command similar to the following:
./orientdb-neo4j-importer.sh \
-neo4jlibdir /home/santo/neo4j/neo4j-community-3.0.7/lib \
-neo4jdbdir /home/santo/neo4j/data/graph.db_northwind \
-odbdir /home/santo/orientdb/orientdb-community-2.2.12/databases/northwind_import

For further information on how to use the Neo4j to OrientDB Importer, please refer to this section.

Migration output
The following is the output that is written by the Neo4j to OrientDB Importer during the

northwind

database migration:

171

Import Tutorials
Neo4j to OrientDB Importer v.2.2.12-SNAPSHOT - Copyrights (c) 2016 OrientDB LTD
WARNING: 'o' option not found. Defaulting to 'false'.
Please make sure that there are no running servers on:
'/home/santo/neo4j/data/graph.db_northwind' (Neo4j)
and:
'/home/santo/orientdb/orientdb-community-2.2.12/databases/northwind_import' (OrientDB)
Initializing Neo4j...Done
Initializing OrientDB...Done
Importing Neo4j database:
'/home/santo/neo4j/data/graph.db_northwind'
into OrientDB database:
'/home/santo/orientdb/orientdb-community-2.2.12/databases/northwind_import'
Getting all Nodes from Neo4j and creating corresponding Vertices in OrientDB...
1035 OrientDB Vertices have been created (100% done)
Done
Creating internal Indices on property 'Neo4jNodeID' on all OrientDB Vertices Classes...
5 OrientDB Indices have been created (100% done)
Done
Getting all Relationships from Neo4j and creating corresponding Edges in OrientDB...
3139 OrientDB Edges have been created (100% done)
Done
Getting Constraints from Neo4j and creating corresponding ones in OrientDB...
0 OrientDB Indices have been created
Done
Getting Indices from Neo4j and creating corresponding ones in OrientDB...
5 OrientDB Indices have been created (100% done)
Done
Import completed!
Shutting down OrientDB...Done
Shutting down Neo4j...Done
===============
Import Summary:
===============
- Found Neo4j Nodes

: 1035

-- With at least one Label

:

--- With multiple Labels

:

-- Without Labels

:

- Imported OrientDB Vertices

: 1035 (100%)

- Found Neo4j Relationships

: 3139

- Imported OrientDB Edges

: 3139 (100%)

- Found Neo4j Constraints

: 0

- Imported OrientDB Constraints (Indices created)

: 0

- Found Neo4j (non-constraint) Indices

: 5

- Imported OrientDB Indices

: 5 (100%)

- Additional created Indices (on vertex properties 'Neo4jNodeID')

: 5

- Total Import time:

: 29 seconds

-- Initialization time

:

7 seconds

-- Time to Import Nodes

:

6 seconds (181.67 nodes/sec)

-- Time to Import Relationships

:

7 seconds (459.79 rels/sec)

-- Time to Import Constraints and Indices

:

4 seconds (1.21 indices/sec)

-- Time to create internal Indices (on vertex properties 'Neo4jNodeID')

:

4 seconds (1.22 indices/sec)

1035
0
0

Connecting to the newly imported Database
172

Import Tutorials
General information on how to connect to a newly imported database can be found in this section.
The following is a partial visualization of the northwind database done with the Graph Editor included in the OrientDB's Studio tool:

As you can see from the Limit field, the visualization is limited to 200 vertices.
The following, instead, is the graph returned by the following
orderID

MATCH

query (the query returns all nodes connected to the Order with

10344):

MATCH {class: Order, where: (orderID = 10344)}--{as: n} RETURN $pathelements

From Studio's Schema M anager, you can check all imported Vertex Classes (node Labels in Neo4j), Edge Classes (Relationship Types in
Neo4j), and Indexes:

173

Import Tutorials

V

and

E

are special classes: they include all Vertices and all Edges.

174

Import Tutorials

This is a legacy strategy to migrate from Neo4j. The new strategy is to migrate using the Neo4j to
OrientDB Importer.

Tutorial: Importing the movie Database from Neo4j
In this tutorial we will follow the steps described in the Import from Neo4j using GraphM L section to import the Neo4j's movie
example database into OrientDB.
We will also provide some examples of queries using the OrientDB's M ATCH syntax, making a comparison with the corresponding
Neo4j's Cypher query language.
For general information on the possible Neo4j to OrientDB migration strategies, please refer to the Import from Neo4j section.
Neo4j and Cypher are registered trademark of Neo Technology, Inc.

Exporting from Neo4j
Assuming you have already downloaded and unpacked the Neo4j Shell Tools, and restarted the Neo4j Server, as described in the Section
Exporting GraphM L, you can export the movie database using

neo4j-shell

with a command like the following one:

D:\neo4j\neo4j-community-3.0.6\bin>neo4j-shell.bat
Welcome to the Neo4j Shell! Enter 'help' for a list of commands
NOTE: Remote Neo4j graph database service 'shell' at port 1337
neo4j-sh (?)$ export-graphml -t -o d:/movie.graphml
Wrote to GraphML-file d:/movies.graphml 0. 100%: nodes = 171 rels = 253 properties = 564 time 270 ms total 270 ms

In the example above the exported movie graph is stored under

D:\movie.graphml

.

Importing into OrientDB
In this tutorial we will import in OrientDB the file

movie.graphml

using the OrientDB's Console. For other GraphM L import methods,

please refer to the section Importing GraphM L.
The OrientDB's Console output generated during the import process is similar to the following (note that first we create a movie
database using the command

CREATE DATABASE

, and then we do the actual import using the command

IMPORT DATABASE

):

D:\orientdb\orientdb-enterprise-2.2.8\bin>console.bat
OrientDB console v.2.2.8-SNAPSHOT (build 2.2.x@r39259e190e16045fe1425b1c0485f8562fca055b; 2016-08-23 14:38:49+0000) www.orient
db.com
Type 'help' to display all the supported commands.
Installing extensions for GREMLIN language v.2.6.0
orientdb> CREATE DATABASE PLOCAL:D:/orientdb/orientdb-enterprise-2.2.8/databases/movie
Creating database [PLOCAL:D:/orientdb/orientdb-enterprise-2.2.8/databases/movie] using the storage type [PLOCAL]...
Database created successfully.
Current database is: PLOCAL:D:/orientdb/orientdb-enterprise-2.2.8/databases/movie
orientdb {db=movie}> IMPORT DATABASE D:/movie.graphml
Importing GRAPHML database from D:/movie.graphml with options ()...
Done: imported 171 vertices and 253 edges
orientdb {db=movie}>

175

Import Tutorials
As you can see from the output above, as a result of the import 171 vertices and 253 edges have been created in OrientDB. This is
exactly the same number of nodes and relationships exported from Neo4j.
For more tips and tricks related to the import process, please refer to this section.

Query Comparison
Once the movie database has been imported into OrientDB, you may use several ways to access its data.
The

MATCH

syntax and the tool Studio can be used, for instance, in a similar way to the Neo4j's Cypher and Browser.

The following sections include a comparison of the Neo4j's Cypher and OrientDB's

MATCH

syntax for some queries that you can

execute against the movie database.

Find the actor named "Tom Hanks"
Neo4j's Cypher:
MATCH (tom:Person {name: "Tom Hanks"})
RETURN tom

OrientDB's M ATCH:
MATCH {class: Person, as: tom, where: (name = 'Tom Hanks')}
RETURN $pathElements

Find the movie with title "Cloud Atlas"
Neo4j's Cypher:
MATCH (cloudAtlas:Movie {title: "Cloud Atlas"})
RETURN cloudAtlas

OrientDB's M ATCH:
MATCH {class: Movie, as: cloudAtlas, where: (title = 'Cloud Atlas')}
RETURN $pathElements

Find 10 people
Neo4j's Cypher:
MATCH (people:Person)
RETURN people.name
LIMIT 10

OrientDB's M ATCH:
MATCH {class: Person, as: people}
RETURN people.name
LIMIT 10

Find the movies released in the 1990s
Neo4j's Cypher:

176

Import Tutorials
MATCH (nineties:Movie)
WHERE nineties.released > 1990 AND nineties.released < 2000
RETURN nineties.title

OrientDB's M ATCH:
MATCH {class: Movie, as: nineties, WHERE: (released > 1990 AND released < 2000 )}
RETURN nineties.title

List all Tom Hanks movies
Neo4j's Cypher:
MATCH (tom:Person {name: "Tom Hanks"})-[:ACTED_IN]->(tomHanksMovies)
RETURN tom, tomHanksMovies

OrientDB's M ATCH:
MATCH {class: Person, as: tom, where: (name = 'Tom Hanks')}-ACTED_IN->{as: tomHanksMovies}
RETURN $pathElements

Find out who directed "Cloud Atlas"
Neo4j's Cypher:
MATCH (cloudAtlas {title: "Cloud Atlas"})<-[:DIRECTED]-(directors)
RETURN directors.name

OrientDB's M ATCH:
MATCH {class: Movie, as: cloudAtlas, where: (title = 'Cloud Atlas')}<-DIRECTED-{as: directors}
RETURN directors.name

Find Tom Hanks' co-actors
Neo4j's Cypher:
MATCH (tom:Person {name:"Tom Hanks"})-[:ACTED_IN]->(m)<-[:ACTED_IN]-(coActors)
RETURN DISTINCT coActors.name

OrientDB's M ATCH:
MATCH {class: Person, as: tom, where: (name = 'Tom Hanks')}-ACTED_IN->{as: m}<-ACTED_IN-{class: Person,as: coActors}
RETURN coActors.name

Find how people are related to "Cloud Atlas"
Neo4j's Cypher:
MATCH (people:Person)-[relatedTo]-(:Movie {title: "Cloud Atlas"})
RETURN people.name, Type(relatedTo), relatedTo

OrientDB's M ATCH:
MATCH {class: Person, as: people}--{as: m, where: (title = 'Cloud Atlas')}
RETURN $pathElements

177

General Information

General Information
This Chapter includes some General Information on OrientDB.

178

Supported Types

Supported Data Types
OrientDB supports several data types natively. Below is the complete table.

#id

Type

S QL type

Description

Autoconversion
from/to

Minimum
Maximum

Java type

0

Boolean

BOOLEAN

Handles only
the values
True or False

java.lang.Boolean
boolean

or

0
1

String

1

Integer

INTEGER

32-bit signed
Integers

java.lang.Integer
int

or

-2,147,483,648
+2,147,483,647

Any
Number,
String

2

Short

SHORT

Small 16-bit
signed
integers

java.lang.Short
short

-32,768
32,767

Any
Number,
String

3

Long

LONG

Big 64-bit
signed
integers

java.lang.Long
long

-263
+263-1

Any
Number,
String

4

Float

FLOAT

Decimal
numbers

java.lang.Float
float

2-149
(2-2-23)*2127

Any
Number,
String

DOUBLE

Decimal
numbers
with high
precision

java.lang.Double
double

2-1074
(2-2-52)*21023

Any
Number,
String

DATETIM E

Any date
with the
precision up
to
milliseconds.
To know
more about
it, look at
M anaging
Dates

java.util.Date

1002020303

Date, Long,
String

java.lang.String

-

-

5

6

Double

Datetime

or

or

or

or

7

String

STRING

Any string
as
alphanumeric
sequence of
chars

8

Binary

BINARY

Can contain
any value as
byte array

byte[]

0
2,147,483,647

String

EM BEDDED

The Record
is contained
inside the
owner. The
contained
Record has
no Record
ID

ORecord

-

ORecord

List

0
41,000,000
items

String

9

10

Embedded

Embedded
list

EM BEDDEDLIST

The Records
are contained
inside the
owner. The
contained
records have
no Record
ID's and are
reachable
only by

179

Supported Types
navigating
the owner
record

11

12

13

14

15

16

Embedded
set

Embedded
map

Link

Link list

Link set

Link map

EM BEDDEDSET

The Records
are contained
inside the
owner. The
contained
Records have
no Record
ID and are
reachable
only by
navigating
the owner
record

Set

0
41,000,000
items

EM BEDDEDM AP

The Records
are contained
inside the
owner as
values of the
entries, while
the keys can
only be
Strings. The
contained
ords e no
Record IDs
and are
reachable
only by
navigating
the owner
Record

Map

0
41,000,000
items

LINK

Link to
another
Record. It's a
common
one-to-one
relationship

ORID , 

1:-1
32767:2^63-1

String

LINKLIST

Links to
other
Records. It's
a common
one-to-many
relationship
where only
the Record
IDs are
stored

List

0
41,000,000
items

Map

0
41,000,000
items

LINKM AP

Links to
other
Records as
value of the
entries, while
keys can
only be
Strings. It's a
common
One-toM any
Relationship.
Only the
Record IDs

String

Collection>
String

,

Collection
String

,

String

180

Supported Types
are stored

17

Byte

BYTE

Single byte.
Useful to
store small
8-bit signed
integers

18

Transient

TRANSIENT

Any value
not stored on
database

DATE

Any date as
year, month
and day. To
know more
about it, look
at M anaging
Dates

19

20

21

22

23

Date

Custom

Decimal

LinkBag

Any

-128
+127

Any
Number,
String

java.util.Date

--

Date, Long,
String

CUSTOM

used to store
a custom
type
providing the
marshall and
unmarshall
methods

OSerializableStream

0
X

-

DECIM AL

Decimal
numbers
without
rounding

java.math.BigDecimal

?
?

Any
Number,
String

LINKBAG

List of
Record IDs
as spec
RidBag

ORidBag

?
?

-

ANY

Not
determinated
type, used to
specify
Collections
of mixed
type, and
null

-

-

java.lang.Byte
byte

-

or

181

Schema

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.
S chema-full Enables strict-mode at a class-level and sets all fields as mandatory.
S chema-less Enables classes with no properties. Default is non-strict-mode, meaning that records can have arbitrary fields.
S chema-hybrid Enables classes with some fields, but allows records to define custom fields. This is also sometimes called schemamixed.
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
records in the class

Account

Account

on the database. It simultaneously creates the physical cluster

account

, to provide storage for

.

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
returns

NULL

Account

. If the query finds that the

Account

class does not exist, it

.

182

Schema

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
TRUE

setStrictMode()

method to

. 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
REMOVE

UPDATE...

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.

183

Schema
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

link to a record of the class

Invoice

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.
An ordered list of links.

LINKLIST
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
184

Schema
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()

Read Only:

setReadonly()

Not Null:

setNotNull()

This field is required.
This field cannot update after being created.

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,

185

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

For more information about indexes look at Index guide.

186

Inheritance

Inheritance
Unlike many Object-relational mapping tools, OrientDB does not split documents between different classes. Each document resides in
one or a number of clusters associated with its specific class. When you execute a query against a class that has subclasses, OrientDB
searches the clusters of the target class and all subclasses.

Declaring Inheritance in Schema
In developing your application, bear in mind that OrientDB needs to know the class inheritance relationship. This is an abstract concept
that applies to both POJO's and Documents.
For example,
OClass account = database.getMetadata().getSchema().createClass("Account");
OClass company = database.getMetadata().getSchema().createClass("Company").setSuperClass(account);

Using Polymorphic Queries
By default, OrientDB treats all queries as polymorphic. Using the example above, you can run the following query from the console:
orientdb>

SELECT FROM Account WHERE name.toUpperCase() = 'GOOGLE'

This query returns all instances of the classes

Account

and

Company

that have a property name that matches

Google

.

How Inheritance Works
Consider an example, where you have three classes, listed here with the cluster identifier in the parentheses.
Account(10) <|--- Company (13) <|--- OrientTechnologiesGroup (27)

By default, OrientDB creates a separate cluster for each class. It indicates this cluster by the
OClass
int[]

and indicates the cluster used by default when not specified. However, the class

), that contains all the clusters able to contain the records of that class.

clusterIds

defaultClusterId

OClass

and

property in the class

has a property

defaultClusterId

clusterIds

, (as

are the same by

default.
When you execute a query against a class, OrientDB limits the result-sets to only the records of the clusters contained in the
clusterIds

property. For example,

orientdb>

SELECT FROM Account WHERE name.toUpperCase() = 'GOOGLE'

This query returns all the records with the name property set to
specified. For the class

Account

GOOGLE

, OrientDB searches inside the clusters

from all three classes, given that the base class
10

,

13

and

27

Account

was

, following the inheritance specified in the

schema.

187

Concurrency

Concurrency
OrientDB uses an optimistic approach to concurrency. Optimistic Concurrency Control, or OCC assumes that multiple transactions can
compete frequently without interfering with each other. It's very important that you don't share instances of databases, graphs, records,
documents, vertices and edges between threads because they are non thread-safe. For more information look at M ulti-Threading.

How does it work?
Consider the following scenario, where 2 clients, A and B, want to update the amount of a bank account:
Client A

Client B

|

|

(t1)

|

Read record #13:22

|

amount is 100

(t2)

|

Read record #13:22

(t3)

amount is 100

Update record #13:22

|

set amount = amount + 10

(t4)

|
|

Update record #13:22
set amount = amount + 10

|

|

Client A (t1) and B (t2) read the record #13:22 and both receive the last amount as USD 100. Client A updates the amount by adding
USD 10 (t3), then the Client B is trying to do the same thing: updates the amount by adding USD 10. Here is the problem: Client B is
doing an operation based on current information: the amount was USD 100. But at the moment of update, such information is changed
(by Client A on t3), so the amount is USD 110 in the database. Should the update succeed by setting the new amount to USD 120?
In some cases this could be totally fine, in others not. It depends by the use case. For example, in your application there could be a logic
where you are donating USD 10 to all the accounts where the amount is <=100. The owner of the account behind the record #13:22 is
more lucky than the others, because it receives the donation even if it has USD 110 at that moment.
For this reason in OrientDB when this situation happens a

OConcurrentModificationException

exception is thrown, so the application

can manage it properly. Usually the 3 most common strategies to handle this exceptions are:
1. Retry doing the same operation by reloading the record #13:22 first with the updated amount
2. Ignore the change, because the basic condition is changed
3. Propagate the exception to the user, so he can decide what to do in this case

Optimistic Concurrency in OrientDB
Optimistic concurrency control is used in environments with low data contention. That is, where conflicts are rare and transactions can
complete without the expense of managing locks and without having transactions wait for locks to clear. This means a reduced
throughput over other concurrency control methods.
OrientDB uses OCC for both Atomic Operations and Transactions.

Atomic Operations
OrientDB supports M ulti-Version Concurrency Control, or M VCC, with atomic operations. This allows it to avoid locking server side
resources. At the same time, it checks the version in the database. If the version is equal to the record version contained in the operation,
the operation is successful. If the version found is higher than the record version contained in the operation, then another thread or user
has already updated the same record. In this case, OrientDB generates an

OConcurrentModificationException

exception.

Given that behavior of this kind is normal on systems that use optimistic concurrency control, developers need to write concurrencyproof code. Under this design, the application retries transactions x times before reporting the error. It does this by catching the
exception, reloading the affected records and attempting to update them again. For example, consider the code for saving a document,

188

Concurrency
int maxRetries = 10;
List result = db.query("SELECT FROM Client WHERE id = '39w39D32d2d'");
ODocument address = result.get(0);
for (int retry = 0; retry < maxRetries; ++retry) {
try {
// LOOKUP FOR THE INVOICE VERTEX
address.field( "street", street );
address.field( "zip", zip );
address.field( "city", cityName );
address.field( "country", countryName );
address.save();
// EXIT FROM RETRY LOOP
break;
}
catch( ONeedRetryException e ) {
// IF SOMEONE UPDATES THE ADDRESS DOCUMENT
// AT THE SAME TIME, RETRY IT.
}
}

Transactions
OrientDB supports optimistic transactions. The database does not use locks when transactions are running, but when the transaction
commits, each record (document or graph element) version is checked to see if there have been updates from another client. For this
reason, you need to code your applications to be concurrency-proof.
Optimistic concurrency requires that you retire the transaction in the event of conflicts. For example, consider a case where you want to
connect a new vertex to an existing vertex:
int maxRetries = 10;
for (int retry = 0; retry < maxRetries; ++retry) {
try {
// LOOKUP FOR THE INVOICE VERTEX
Vertex invoice = graph.getVertices("invoiceId", 2323);
// CREATE A NEW ITEM
Vertex invoiceItem = graph.addVertex("class:InvoiceItem");
invoiceItem.field("price", 1000);
// ADD IT TO THE INVOICE
invoice.addEdge(invoiceItem);
graph.commit();
// EXIT FROM RETRY LOOP
break;
}
catch( OConcurrentModificationException e ) {
// SOMEONE HAS UPDATED THE INVOICE VERTEX
// AT THE SAME TIME, RETRY IT
}
}

Concurrency Level
Before v2.2.4, transactions acquire an exclusive lock on the storage, so no matter if you have 1 or 100 cores, the execution was always
serialized. With 2.2.4 and further, transactions are executed in parallel only if they involve different clusters and indexes.
In order to use the transaction parallelism, the domain has to be slightly changed by using the OrientDB inheritance by creating a base
class and multiple sub-classes, one per core. Example of creating the class Log with 4 sub-classes (4 cores) and the indexed property 'id':

189

Concurrency
CREATE CLASS Log ABSTRACT
CREATE CLASS Log_1 EXTENDS Log
CREATE PROPERTY Log_1.id STRING
CREATE INDEX Log1Id ON Log_1(id) UNIQUE_HASHINDEX
CREATE CLASS Log_2 EXTENDS Log
CREATE PROPERTY Log_2.id STRING
CREATE INDEX Log1Id ON Log_2(id) UNIQUE_HASHINDEX
CREATE CLASS Log_3 EXTENDS Log
CREATE PROPERTY Log_3.id STRING
CREATE INDEX Log1Id ON Log_3(id) UNIQUE_HASHINDEX
CREATE CLASS Log_4 EXTENDS Log
CREATE PROPERTY Log_4.id STRING
CREATE INDEX Log1Id ON Log_4(id) UNIQUE_HASHINDEX

After creating multiple sub-classes, you should bind your threads/client (it depends, respectively, if you are working in embedded mode
or client/server) to a different sub-class. For example with 4 cores, you have 4 sub-classes (like above) and this could be the binding for
the class "Log":
Thread/Client 1 -> Class Log_1
Thread/Client 2 -> Class Log_2
Thread/Client 3 -> Class Log_3
Thread/Client 4 -> Class Log_4
If you are working with graphs, it's a good practice to apply the same rule to both vertex and edge classes. In this example we have 4
cores, so 4 clusters per vertex class and 4 clusters per edge class:
Thread/Client 1 -> Classes User_1 and City_1 for vertices and Class Born_1 for edges
Thread/Client 2 -> Classes User_2 and City_2 for vertices and Class Born_2 for edges
Thread/Client 3 -> Classes User_3 and City_3 for vertices and Class Born_3 for edges
Thread/Client 4 -> Classes User_4 and City_4 for vertices and Class Born_4 for edges
Now look at these 2 SQL scripts:
Client 1:
BEGIN
LET v1 = CREATE VERTEX User_1 SET name = 'Luca'
LET v2 = CREATE VERTEX City_1 SET name = 'Rome'
CREATE EDGE Born_1 FROM $v1 TO $v2
COMMIT RETRY 10

Client 2:
BEGIN
LET v1 = CREATE VERTEX User_2 SET name = 'Luca'
LET v2 = CREATE VERTEX City_2 SET name = 'Rome'
CREATE EDGE Born_2 FROM $v1 TO $v2
COMMIT RETRY 10

In this case the two transactions go in parallel with no conflict, because they work on different classes and indexes.
Thanks to the OrientDB polymorphism, sub-classes are

instance of

the abstract class, so you can still execute queries by using the

base class as target and OrientDB will consider all the sub-classes, so your model remains clean at application level. Example:
SELECT * FROM User WHERE name = 'Luca'

But if you already know that Luca if exists is in the 2nd partition of the User class (User_2 sub class), you can also execute:
SELECT * FROM User_2 WHERE name = 'Luca'

190

Concurrency
When it's possible to pre-determine there the record is saved, using the sub-class as target has better performance.

Concurrency when Adding Edges
Consider the case where multiple clients attempt to add edges on the same vertex. OrientDB could throw the
OConcurrentModificationException

exception. This occurs because collections of edges are kept on vertices, meaning that, every time

OrientDB adds or removes an edge, both vertices update and their versions increment. You can avoid this issue by using RIDBAG
Bonsai structure, which are never embedded, so the edge never updates the vertices.
To use this configuration at run-time, before launching OrientDB, use this code:
OGlobalConfiguration.RID_BAG_EMBEDDED_TO_SBTREEBONSAI_THRESHOLD.setValue(-1);

Alternatively, you can set a parameter for the Java virtual-machine on startup, or even at run-time, before OrientDB is used:
$

java -DridBag.embeddedToSbtreeBonsaiThreshold=-1

While running in distributed mode S BTrees are not supported. If using a distributed database
then you must set
ridBag.embeddedToSbtreeBonsaiThreshold = Integer.MAX\_VALUE
to avoid replication errors.

Troubleshooting
Reduce Transaction Size
On occasion, OrientDB throws the

OConcurrentModificationException

exception even when you concurrently update the first element.

In particularly large transactions, where you have thousands of records involved in a transaction, one changed record is enough to roll the
entire process back with an

OConcurrentModificationException

exception.

To avoid issues of this kind, if you plan to update many elements in the same transaction with high-concurrency on the same vertices, a
best practice is to reduce the transaction size.

191

Indexing

Indexes
OrientDB supports four index algorithms:
S B-Tree Index Provides a good mix of features available from other index types, good for general use. It is durable, transactional
and supports range queries. It is the default index type.
Hash Index Provides fast lookup and is very light on disk usage. It is durable and transactional, but does not support range
queries. It works like a HashM ap, which makes it faster on punctual lookups and it consumes less resources than other index
types.
Auto S harding Index Provides an implementation of a DHT. It is durable and transactional, but does not support range queries.
(Since v2.2)
Lucene Full Text Index Provides good full-text indexes, but cannot be used to index other types. It is durable, transactional and
supports range queries.
Lucene S patial Index Provides good spatial indexes, but cannot be used to index other types. It is durable, transactional and
supports range queries.

Understanding Indexes
OrientDB can handle indexes in the same manner as classes, using the SQL language and prefixing the name with

index:

followed by

the index name. An index is like a class with two properties:
key

The index key.

rid

The Record ID, which points to the record associated with the key.

Index Target
OrientDB can use two methods to update indexes:
Automatic Where the index is bound to schema properties. (For example,

User.id

.) If you have a schema-less database and you

want to create an automatic index, then you need to create the class and the property before using the index.
Manual Where the index is handled by the application developer, using the Java API and SQL commands (see below). You can use
them as Persistent M aps, where the entry's value are the records pointed to by the index.
You can rebuild automatic indexes using the

REBUILD INDEX

command.

Index Types
When you create an index, you create it as one of several available algorithm types. Once you create an index, you cannot change its
type. OrientDB supports four index algorithms and several types within each. You also have the option of using any third-party index
algorithms available through plugins.
S B-Tree Algorithm
UNIQUE

These indexes do not allow duplicate keys. For composite indexes, this refers to the uniqueness of the composite

keys.
These indexes allow duplicate keys.

NOTUNIQUE
FULLTEXT

These indexes are based on any single word of text. You can use them in queries through the

CONTAINSTEXT

operator.
DICTIONARY

These indexes are similar to those that use

UNIQUE

, but in the case of duplicate keys, they replaces the existing

record with the new record.
HashIndex Algorithm
UNIQUE_HASH_INDEX

These indexes do not allow duplicate keys. For composite indexes, this refers to the uniqueness of the

composite keys. Available since version 1.5.x.
NOTUNIQUE_HASH_INDEX
FULLTEXT_HASH_INDEX
CONTAINSTEXT

These indexes allow duplicate keys. Available since version 1.5.x.
These indexes are based on any single word of text. You can use them in queries through the

operator. Available since version 1.5.x.

192

Indexing
DICTIONARY_HASH_INDEX

These indexes are similar to those that use

UNIQUE_HASH_INDEX

, but in cases of duplicate keys, they

replaces the existing record with the new record. Available since version 1.5.x.
HashIndex Algorithm (Since v2.2)
UNIQUE_HASH_INDEX

These indexes do not allow duplicate keys. For composite indexes, this refers to the uniqueness of the

composite keys.
NOTUNIQUE_HASH_INDEX

These indexes allow duplicate keys.

Lucene Engine
FULLTEXT

These indexes use the Lucene engine to index string content. You can use them in queries with the

LUCENE

operator.
SPATIAL

These indexes use the Lucene engine to index geospatial coordinates.

Every database has a default manual index type

DICTIONARY

, which uses strings as keys. You may find this useful in handling the root

records of trees and graphs, and handling singleton records in configurations.

Indexes and Null Values
Starting from v2.2, Indexes do not ignore NULL values, but they are indexes as any other values. This means that if you have a
UNIQUE index, you cannot have multiple NULL keys. This applies only to the new indexes, opening a database with indexes
previously created, will all ignore NULL by default.
To create an index that expressly ignore nulls (like the default with v2.1 and earlier), look at the following examples by using SQL or
Java API.
SQL:
orientdb>

CREATE INDEX addresses ON Employee (address) NOTUNIQUE METADATA {ignoreNullValues: true}

And Java API:
schema.getClass("Employee").getProperty("address").createIndex(OClass.INDEX_TYPE.NOTUNIQUE, new ODocument().field("ignoreNullV
alues",true));

Indexes and Composite Keys
Operations that work with indexes also work with indexes formed from composite keys. By its nature, a composite key is a collection
of values, so, syntactically, it is a collection.
For example, consider a case where you have a class

Book

, indexed by three fields:

author

,

title

and

publicationYear

. You might

use the following query to look up an individual book:
orientdb>

SELECT FROM INDEX:books WHERE key = ["Donald Knuth", "The Art of Computer

Programming", 1968]

Alternatively, you can look for books over a range of years with the field
orientdb>

publicationYear

:

SELECT FROM INDEX:books WHERE key BETWEEN ["Donald Knuth", "The Art of

Computer Programming", 1960] AND ["Donald Knuth", "The Art of Computer
Programming", 2000]

Partial Match Searches
Occasionally, you may need to search an index record by several fields of its composite key. In these partial match searches, the
remaining fields with undefined values can match any value in the result.

193

Indexing
Only use composite indexes for partial match searches when the declared fields in the composite index are used from left to right. For
instance, from the example above searching only
you could use it when searching

author

and

title

title

wouldn't work with a composite index, since

title

is the second value. But,

.

For example, consider a case where you don't care when the books in your database were published. This allows you to use a somewhat
different query, to return all books with the same author and title, but from any publication year.
orientdb>

SELECT FROM INDEX:books WHERE key = ["Donald Knuth", "The Art of Computer

Programming"]

In the event that you also don't know the title of the work you want, you can further reduce it to only search all books with the same
author.
orientdb>

SELECT FROM INDEX:books WHERE key = ["Donald Knuth"]

Or, the equal,
orientdb>

SELECT FROM INDEX:books WHERE key = "Donald Knuth"

Range Queries
Not all the indexes support range queries (check above). In the case of range queries, the field subject to the range must be the last one,
(that is, the one on the far right). For example,
orientdb>

SELECT FROM INDEX:books WHERE key BETWEEN ["Donald Knuth", "The Art of

Computer Programming", 1900] AND ["Donald Knuth", "The Art of Computer
Programming", 2014]

Operations against Indexes
Once you have a good understanding of the theoretical side of what indexes are and some of basic concepts that go into their use, it's
time to consider the practical aspects of creating and using indexes with your application.

Creating Indexes
When you have created the relevant classes that you want to index, create the index. To create an automatic index, bound to a schema
property, use the

ON

section or use the name in the

.

notation.

S yntax:
CREATE INDEX  [ON  (prop-names)]  []
[METADATA {}]



Provides the logical name for the index. You can also use the

bound to a schema property. In this case, for





use the class of the schema and

notation to create an automatic index


the property created in the

class.
Bear in mind that this means case index names cannot contain the period (

.

) symbol, as OrientDB would interpret the text after

as a property.


Provides the name of the class that you are creating the automatic index to index. This class must already exist in

the database.


Provides a comma-separated list of properties, which you want the automatic index to index. These properties

must already exist in the schema.

194

Indexing
If the property belongs to one of the M ap types, (such as

LINKMAP

in generating indexes. You can do this with the

BY VALUE

BY KEY

or

, or

EMBEDDEDMAP

), you can specify the keys or values to use

expressions, if nothing is specified, these keys are used

during index creation.


Provides the algorithm and type of index that you want to create. For information on the supported index types, see

Index Types.


Provides the optional key type. With automatic indexes, the key type OrientDB automatically determines the key

type by reading the target schema property where the index is created. With manual indexes, if not specified, OrientDB
automatically determines the key type at run-time, during the first insertion by reading the type of the class.


Provides a JSON representation

Examples:
Creating custom indexes, deprecated since 3.0:
orientdb>

CREATE INDEX mostRecentRecords UNIQUE date

Creating another index for the property

id

of the class

User

orientdb>

CREATE PROPERTY User.id BINARY

orientdb>

CREATE INDEX indexForId ON User (id) UNIQUE

Creating indexes for property

thumbs

on class

Movie

:

:

orientdb>

CREATE INDEX thumbsAuthor ON Movie (thumbs) UNIQUE

orientdb>

CREATE INDEX thumbsAuthor ON Movie (thumbs BY KEY) UNIQUE

orientdb>

CREATE INDEX thumbsValue on Movie (thumbs BY VALUE) UNIQUE

Creating composite indexes:
orientdb>

CREATE PROPERTY Book.author STRING

orientdb>

CREATE PROPERTY Book.title STRING

orientdb>

CREATE PROPERTY Book.publicationYears EMBEDDEDLIST INTEGER

orientdb>

CREATE INDEX books ON Book (author, title, publicationYears) UNIQUE

For more information on creating indexes, see the

CREATE INDEX

command.

Dropping Indexes
In the event that you have an index that you no longer want to use, you can drop it from the database. This operation does not remove
linked records.
S yntax:
DROP INDEX 



provides the name of the index you want to drop.

For more information on dropping indexes, see the

DROP INDEX

command.

Querying Indexes
When you have an index created and in use, you can query records in the index using the

SELECT

command.

S yntax:

195

Indexing
SELECT FROM INDEX: WHERE key = 

Example:
Selecting from the index
orientdb>

dictionary

where the key matches to

Luke

:

SELECT FROM INDEX:dictionary WHERE key='Luke'

Case-insensitive Matching with Indexes
In the event that you would like the index to use case-insensitive matching, set the

COLLATE

attribute of the indexed properties to

ci

.

For instance,
orientdb>

CREATE INDEX OUser.name ON OUser (name COLLATE ci) UNIQUE

Inserting Index Entries
You can insert new entries into the index using the

key

and

rid

pairings.

S yntax:
INSERT INTO INDEX: (key,rid) VALUES (,)

Example:
Inserting the key
orientdb>

Luke

and Record ID

#10:4

into the index

dictionary

:

INSERT INTO INDEX:dictionary (key, rid) VALUES ('Luke', #10:4)

Querying Index Ranges
In addition to querying single results from the index, you can also query a range of results between minimum and maximum values. Bear
in mind that not all index types support this operation.
S yntax:
SELECT FROM INDEX: WHERE key BETWEEN  AND 

Example:
Querying from the index
orientdb>

coordinates

and range between

10.3

and

10.7

:

SELECT FROM INDEX:coordinates WHERE key BETWEEN 10.3 AND 10.7

Removing Index Entries
You can delete entries by passing the

key

and

values. This operation returns

rid

TRUE

if the removal was successful and

FALSE

if

the entry wasn't found.
S yntax:
DELETE FROM INDEX: WHERE key =  AND rid = 

Example:
Removing an entry from the index

dictionary

:

196

Indexing

orientdb>

DELETE FROM INDEX:dictionary WHERE key = 'Luke' AND rid = #10:4

Removing Index Entries by Key
You can delete all entries from the index through the requested key.
S yntax:
DELETE FROM INDEX: WHERE key = 

Example:
Delete entries from the index
orientdb>

whee the key matches to

addressbook

Luke

:

DELETE FROM INDEX:addressbook WHERE key = 'Luke'

Removing Index Entries by RID
You can remove all index entries to a particular record by its record ID.
S yntax:
DELETE FROM INDEX: WHERE rid = 

Example:
Removing entries from index
orientdb>

dictionary

tied to the record ID

#10:4

:

DELETE FROM INDEX:dictionary WHERE rid = #10:4

Counting Index Entries
To see the number of entries in a given index, you can use the

COUNT()

function.

S yntax:
SELECT COUNT(*) AS size FROM INDEX:

Example:
Counting the entries on the index
orientdb>

dictionary

:

SELECT COUNT(*) AS size FROM INDEX:dictionary

Querying Keys from Indexes
You can query all keys in an index using the

SELECT

command.

S yntax:
SELECT key FROM INDEX:

Example:
Querying the keys in the index
orientdb>

dictionary

:

SELECT key FROM INDEX:dictionary

197

Indexing

Querying Index Entries
You can query for all entries on an index as

key

and

rid

pairs.

S yntax:
SELECT key, value FROM INDEX:

Example:
Querying the

key

orientdb>

/

rid

pairs from the index

dictionary

:

SELECT key, value FROM INDEX:dictionary

Clearing Indexes
Remove all entries from an index. After running this command, the index is empty.
S yntax:
DELETE FROM INDEX:

Example:
Removing all entries from the index
orientdb>

dictionary

:

DELETE FROM INDEX:dictionary

Query the available indexes
To access to the indexes, you can use SQL.

Create your index engine
Here you can find a guide how to create a custom index engine.

198

SB-Tree

SB-Tree Index Algorithm
This indexing algorithm provides a good mix of features, similar to the features available from other index types. It is good for general use
and is durable, transactional and supports range queries. There are four index types that utilize the SB-Tree index algorithm:
UNIQUE

Does not allow duplicate keys, fails when it encounters duplicates.
Does allow duplicate keys.

NOTUNIQUE
FULLTEXT

Indexes to any single word of text.

DICTIONARY

Does not allow duplicate keys, overwrites when it encounters duplicates.

For more information on

FULLTEXT_HASH_INDEX

, see FullText Index.

The SB-Tree index algorithm is based on the B-Tree index algorithm. It has been adapted with several optimizations, which relate to data
insertion and range queries. As is the case with all other tree-based indexes, SB-Tree index algorithm experiences

log(N)

complexity,

but the base to this logarithm is about 500.
NOTE: There is an issue in the replacement of indexes based on B-Tree with those based on COLA Tree to avoid slowdowns
introduced by random I/O operations. For more information see Issue #1756.

199

Hash

Hash Index Algorithm
This indexing algorithm provides a fast lookup and is very light on disk usage. It is durable and transactional, but does not support range
queries. It is similar to a HashM ap, which makes it faster on punctual lookups and it consumes less resources than other index types.
The Hash index algorithm supports four index types, which have been available since version 1.5.x:
UNIQUE_HASH_INDEX

Does not allow duplicate keys, it fails when it encounters duplicates.
Does allow duplicate keys.

NOTUNIQUE_HASH_INDEX
FULLTEXT_HASH_INDEX
DICTIONARY

Indexes to any single word.

Does not allow duplicate keys, it overwrites when it encounters duplicates.

For more information on

FULLTEXT_HASH_INDEX

, see FullText Index.

Hash indexes are able to perform index read operations in one I/O operation and write operations in a maximum of three I/O operations.
The Hash Index algorithm is based on the Extendible Hashing algorithm. Despite not providing support for range queries, it is noticeably
faster than SB-Tree Index Algorithms, (about twice as fast when querying through ten million records).
NOTE: There is an issue relating to the enhancement of Hash indexes to avoid slowdowns introduced by random I/O operations
using LSM Tree approaches. For more information, see Issue #1757.

200

Auto-Sharding

Auto Sharding Index Algorithm
(Since v2.2)
This indexing algorithm is based on the DHT concept, where they keys are stored on different partition, based on the M urmur3 hash
function.
Auto Sharding Index supports the following index types:
UNIQUE_HASH_INDEX

Does not allow duplicate keys, it fails when it encounters duplicates.

NOTUNIQUE_HASH_INDEX

Does allow duplicate keys.

Under the hood, this index creates multiple Hash Indexes, one per cluster. So if you have 8 clusters for the class "Employee", this index
will create, at the beginning, 8 Hash Indexes.
Since this index is based on the Hash Index, it's able to perform index read operations in one I/O operation and write operations in a
maximum of three I/O operations. The Hash Index algorithm is based on the Extendible Hashing algorithm. Despite not providing
support for range queries, it is noticeably faster than SB-Tree Index Algorithms, (about twice as fast when querying through ten million
records).

Usage
Create an index by passing "AUTOSHARDING" as index engine:
final OClass cls = db.createClass("Log");
cls.createProperty("key", OType.LONG);
cls.createIndex("idx_LogKey", OClass.INDEX_TYPE.UNIQUE.toString(),
(OProgressListener) null, (ODocument) null, "AUTOSHARDING", new String[] { "key" });

Performance
On multi-core hw, using this index instead of Hash Index gives about +50% more throughput on insertion on a 8 cores machine.

Distributed
The fully distributed version of this index will be supported in v3.0. In v2.2 each node has own copy of the index with all the partitions.

Internals
This is the algorithm for the

put(key,value)

:

int partition = Murmur3_hash(key) % partitions;
getSubIndex(partition).put(key,value);

This is for the

value = get(key)

:

int partition = Murmur3_hash(key) % partitions;
return getSubIndex(partition).get(key);

201

Full Text

FullText Indexes
The SB-Tree index algorithm provides support for FullText indexes. These indexes allow you to index text as a single word and its radix.
FullText indexes are like having a search engine on your database.
NOTE: Bear in mind that there is a difference between
with the SB-Tree index algorithm and

FULLTEXT

FULLTEXT

with the

LUCENE

without the

LUCENE

operator, which uses a FullText index

operator, which uses a FullText index through the Lucene

Engine.
For more information on the latter, see Lucene FullText Index.

Creating FullText Indexes
If you want to create an index using the FullText SB-Tree index algorithm, you can do so using the
orientdb>

CREATE INDEX

command.

CREATE INDEX City.name ON City(name) FULLTEXT

This creates a FullText index on the property

name

of the class

City

, using the default configuration.

FullText Index Parameters
In the event that the default FullText Index configuration is not sufficient to your needs, there are a number of parameters available to
fine tune how it generates the index.
Parameter

Default

Description

indexRadix

TRUE

Word prefixes will be also
index

ignoreChars

"

Chars to skip when
indexing

separatorChars

\r\n\t:;,.|+*/\=!?[](.md)

minWordLength

3

stopWords

M inimum word length to
index

the in a at as and or for his her him this that what which while up
with be was were is

Stop words escluded from
indexing

To configure a FullText Index, from version 1.7 on, you can do so through the OrientDB console or the Java API. When configuring the
index from the console, use the
orientdb>

CREATE INDEX

command with the

METADATA

operator.

CREATE INDEX City.name ON City(name) FULLTEXT METADATA

{"indexRadix": true, "ignoreChars": "&", "separatorChars": " |()",
"minWordLength": 4, "stopWords": ["the", "of"]}

Alternatively, you can configure the index in Java.
OClass city = db.getClass("City");
ODocument metadata = new ODocument();
metadata.field("indexRadix", true);
metadata.field("stopWords", Arrays.asList(new String[] { "the", "in", "a", "at" }));
metadata.field("separatorChars", " :;?[](.md)");
metadata.field("ignoreChars", "$&");
metadata.field("minWordLength", 5);
city.createIndex("City.name", "FULLTEXT", null, metadata, null, new String[] { "name" });

202

Lucene Full Text

Lucene FullText Index
In addition to the standard FullText Index, which uses the SB-Tree index algorithm, you can also create FullText indexes using the
Lucene Engine . Apache LuceneTM is a high-performance, full-featured text search engine library written entirely in Java. Check the
Lucene documentation for a full overview of its capabilities.

How Lucene's works?
Let's look at a sample corpus of five documents:
M y sister is coming for the holidays.
The holidays are a chance for family meeting.
Who did your sister meet?
It takes an hour to make fudge.
M y sister makes awesome fudge.
What does Lucene do? Lucene is a full text search library. Search has two principal stages: indexing and retrieval.
During indexing, each document is broken into words, and the list of documents containing each word is stored in a list called the
postings list. The posting list for the word my is:
my --> 1,5
Posting list for others terms:
fudge --> 4,5
sister --> 1,2,3,5
fudge --> 4,5
The index consists of all the posting lists for the words in the corpus. Indexing must be done before retrieval, and we can only retrieve
documents that were indexed.
Retrieval is the process starting with a query and ending with a ranked list of documents. Say the query is "my fudge". In order to find
matches for the query, we break it into the individual words, and go to the posting lists. The full list of documents containing the
keywords is [1,4,5]. Note that the query is broken into words (terms) and each term is matched with the terms in the index. Lucene's
default operator is OR, so it retrieves the documents tha contain my OR fudge. If we want to retrieve documents that contain both my
and fudge, rewrite the query: "+my +fudge".
Lucene doesn't work as a LIKE operator on steroids, it works on single terms. Terms are produced analyzing the provided text, so the
right analyzer should be configured. On the other side, it offers a complete query language, well documented here:

Index creation
To create an index based on Lucene
CREATE INDEX

ON

(prop-names) FULLTEXT ENGINE LUCENE [{json metadata}]

The following SQL statement will create a FullText index on the property

name

for the class

City

, using the Lucene Engine.

CREATE INDEX City.name ON City(name) FULLTEXT ENGINE LUCENE

Indexes can also be created on n-properties. For example, create an index on the properties

name

and

description

on the class

City

.

CREATE INDEX City.name_description ON City(name, description)
FULLTEXT ENGINE LUCENE

203

Lucene Full Text
When multiple properties should be indexed, define a single multi-field index over the class. A single multi-field index needs less
resources, such as file handlers. M oreover, it is easy to write better Lucene queries. The default analyzer used by OrientDB when a
Lucene index is created is the StandardAnalyzer. The StandardAnalyzer usually works fine with western languages, but Lucene offers
analyzer for different languages and use cases.

Two minutes tutorial
Open studio or console and create a sample dataset:
CREATE CLASS Item;
CREATE PROPERTY Item.text STRING;
CREATE INDEX Item.text ON Item(text) FULLTEXT ENGINE LUCENE;
INSERT INTO Item (text) VALUES ('My sister is coming for the holidays.');
INSERT INTO Item (text) VALUES ('The holidays are a chance for family meeting.');
INSERT INTO Item (text) VALUES ('Who did your sister meet?');
INSERT INTO Item (text) VALUES ('It takes an hour to make fudge.');
INSERT INTO Item (text) VALUES ('My sister makes awesome fudge.');

Search all documents that contain sister:
SELECT FROM Item WHERE SEARCH_CLASS("sister") = true

Search all documents that contain sister AND coming:
SELECT FROM Item WHERE SEARCH_CLASS("+sister +coming") = true

Search all documents that contain sister but NOT coming:
SELECT FROM Item WHERE SEARCH_CLASS("+sister -coming") = true

Search all documents that contain the phrase sister meet:
SELECT FROM Item WHERE SEARCH_CLASS(' "sister meet" ') = true

Search all documents that contain terms starting with meet:
SELECT FROM Item WHERE SEARCH_CLASS('meet*') = true

To better understand how the query parser work, read carefully the official documentation and play with the above documents.

Customize Analyzers
In addition to the StandardAnalyzer, full text indexes can be configured to use different analyzer by the
CREATE INDEX

METADATA

operator through

.

Configure the index on

City.name

to use the

EnglishAnalyzer

:

CREATE INDEX City.name ON City(name)
FULLTEXT ENGINE LUCENE METADATA {
"analyzer": "org.apache.lucene.analysis.en.EnglishAnalyzer"
}

Configure the index on

City.name

to use different analyzers for indexing and querying.

204

Lucene Full Text
CREATE INDEX City.name ON City(name)
FULLTEXT ENGINE LUCENE METADATA {
"index": "org.apache.lucene.analysis.en.EnglishAnalyzer",
"query": "org.apache.lucene.analysis.standard.StandardAnalyzer"
}

EnglishAnalyzer

will be used to analyze text while indexing and the

StandardAnalyzer

will be used to analyze query text.

A very detailed configuration, on multi-field index configuration, could be:
CREATE INDEX Song.fulltext ON Song(name, lyrics, title, author, description)
FULLTEXT ENGINE LUCENE METADATA {
"default": "org.apache.lucene.analysis.standard.StandardAnalyzer",
"index": "org.apache.lucene.analysis.core.KeywordAnalyzer",
"query": "org.apache.lucene.analysis.standard.StandardAnalyzer",
"name_index": "org.apache.lucene.analysis.standard.StandardAnalyzer",
"name_query": "org.apache.lucene.analysis.core.KeywordAnalyzer",
"lyrics_index": "org.apache.lucene.analysis.en.EnglishAnalyzer",
"title_index": "org.apache.lucene.analysis.en.EnglishAnalyzer",
"title_query": "org.apache.lucene.analysis.en.EnglishAnalyzer",
"author_query": "org.apache.lucene.analysis.core.KeywordAnalyzer",
"description_index": "org.apache.lucene.analysis.standard.StandardAnalyzer",
"description_index_stopwords": [
"the",
"is"
]
}

With this configuration, the underlying Lucene index will works in different way on each field:
name: indexed with StandardAnalyzer, searched with KeywordAnalyzer (it's a strange choice, but possible)
lyrics: indexed with EnglishAnalyzer, searched with default query analyzer StandardAnalyzer
title: indexed and searched with EnglishAnalyzer
author: indexed and searched with KeywordAnalyzer
description: indexed with StandardAnalyzer with a given set of stop-words that overrides the internal set
Analysis is the foundation of Lucene. By default the StandardAnalyzer removes english stop-words and punctuation and lowercase the
generated terms:
The holidays are a chance for family meeting!
Would produce
holidays
are
chance
for
family
meeting
Each analyzer has its set of stop-words and tokenize the text in a different way. Read the full (documentation)
[http://lucene.apache.org/core/6_6_0/].

Query parser
It is possible to configure some behavior of the Lucene query parser Query parser's behavior can be configured at index creation time and
overridden at runtime.

Allow Leading Wildcard
Lucene by default doesn't support leading wildcard: Lucene wildcard support
It is possible to override this behavior with a dedicated flag on meta-data:

205

Lucene Full Text
{
"allowLeadingWildcard": true
}

CREATE INDEX City.name ON City(name)
FULLTEXT ENGINE LUCENE METADATA {
"allowLeadingWildcard": true
}

Use this flag carefully, as stated in the Lucene FAQ:
Note that this can be an expensive operation: it requires scanning the list of tokens in the index in its entirety to look for those
that match the pattern.

Disable lower case on terms
Lucene's QueryParser applies a lower case filter on expanded queries by default. It is possible to override this behavior with a dedicated
flag on meta-data:
{
"lowercaseExpandedTerms": false
}

It is useful when used in pair with keyword analyzer:
CREATE INDEX City.name ON City(name)
FULLTEXT ENGINE LUCENE METADATA {
"lowercaseExpandedTerms": false,
"default" : "org.apache.lucene.analysis.core.KeywordAnalyzer"
}

With lowercaseExpandedTerms set to false, these two queries will return different results:
SELECT from Person WHERE SEARCH_CLASS("NAME") = true
SELECT from Person WHERE WHERE SEARCH_CLASS("name") = true

Querying Lucene FullText Indexes
OrientDB 3.0.x introduced search functions: SEARCH_CLASS, SEARCH_FIELDS, SEARCH_INDEX, SEARCH_MORE Every function
accepts as last, optional, parameter a JSON with additional configuration.

SEARCH_CLASS
The best way to use the search capabilities of OrientDB is to define a single multi-fields index and use the SEARCH_CLASS function. In
case more than one full-text index are defined over a class, an error is raised in case of SEARCH_CLASSI invocation.
Suppose to have this index
CREATE INDEX City.fulltex ON City(name, description) FULLTEXT ENGINE LUCENE

A query that retrieve cities with the name starting with cas and description containing the word beautiful:
SELECT FROM City WHERE SEARCH_CLASS("+name:cas*

+description:beautiful") = true

The function accepts metadata JSON as second parameter:

206

Lucene Full Text
SELECT FROM City WHERE SEARCH_CLASS("+name:cas*

+description:beautiful", {

"allowLeadingWildcard": true ,
"lowercaseExpandedTerms": false,
"boost": {
"name": 2
},
"highlight": {
"fields": ["name"],
"start": "",
"end": ""
}
}) = true

The query shows query parser's configuration overrides, boost of field name with highlight. Highlight and boost will be explained later.

SEARCH_MORE
OrientDB exposes the Lucene's more like this capability with a dedicated function.
The first parameter is the array of RID of elements to be used to calculate similarity, the second parameter the usual metadata JSON
used to tune the query behaviour.
SELECT FROM City WHERE SEARCH_MORE([#25:2, #25:3],{'minTermFreq':1, 'minDocFreq':1} ) = true

It is possible to use a query to gather RID of documents to be used to calculate similarity:
SELECT FROM City
let $a=(SELECT @rid FROM City WHERE name = 'Rome')
WHERE SEARCH_MORE( $a, { 'minTermFreq':1, 'minDocFreq':1} ) = true

Lucene's M LT has a lot of parameter, and all these are exposed through the metadata JSON:
http://lucene.apache.org/core/6_6_0/queries/org/apache/lucene/queries/mlt/M oreLikeThis.html
fieldNames: array of field's names to be used to extract content
maxQueryTerms
minDocFreq
maxDocFreq
minTermFreq
boost
boostFactor
maxWordLen
minWordLen
maxNumTokensParsed
stopWords

Query parser's runtime configuration
It is possible to override the query parser's configuration given at creation index time at runtime passing a json:
SELECT from Person WHERE SEARCH_CLASS("bob",{
"allowLeadingWildcard": true ,
"lowercaseExpandedTerms": false
} ) = true

The same can be done for query analyzer, overriding the configuration given at index creation's time:
SELECT from Person WHERE SEARCH_CLASS("bob",{
"customAnalysis": true ,
"query": "org.apache.lucene.analysis.standard.StandardAnalyzer",
"name_query": "org.apache.lucene.analysis.en.EnglishAnalyzer"
} ) = true

207

Lucene Full Text
The customAnalysis flag is mandatory to enable the runtime configuration of query analyzers. The runtime configuration is per query
and it isn't stored nor reused for a subsequent query. The custom configuration can be used with all the functions.

SEARCH_INDEX
The SEARCH_INDEX function allows to execute the query on a single index. It is useful if more than one index are defined over a class.
SELECT FROM City WHERE SEARCH_INDEX("City.name", "cas*") = true

The function accepts a JSON as third parameter, as for SEARCH_CLASS.

SEARCH_FIELDS
The SEARCH_FIELDS function allows to execute query over the index that is defined over one ormore fields:
SELECT FROM City WHERE SEARCH_FIELDS(["name", "description"], "name:cas* description:beautiful") = true

The function accepts a JSON as third parameter, as for SEARCH_CLASS.

Numeric and date range queries
If the index is defined over a numeric field (INTEGER, LONG, DOUBLE) or a date field (DATE, DATETIM E), the engine supports
range queries Suppose to have a

City

class witha multi-field Lucene index defined:

CREATE CLASS CITY EXTENDS V
CREATE PROPERTY CITY.name STRING
CREATE PROPERTY CITY.size INTEGER
CREATE INDEX City.name ON City(name,size) FULLTEXT ENGINE LUCENE

Then query using ranges:
SELECT FROM City WHERE SEARCH_CLASS('name:cas* AND size:[15000 TO 20000]') = true

Ranges can be applied to DATE/DATETIM E field as well. Create a Lucene index over a property:
CREATE CLASS Article EXTENDS V
CREATE PROPERTY Article.createdAt DATETIME
CREATE INDEX Article.createdAt

ON Article(createdAt) FULLTEXT ENGINE LUCENE

Then query to retrieve articles published only in a given time range:
SELECT FROM Article WHERE SEARCH_CLASS('[201612221000 TO 201612221100]') =true

Retrieve the Score
When the lucene index is used in a query, the results set carries a context variable for each record representing the score. To display the
score add

$score

in projections.

SELECT *,$score FROM V WHERE name LUCENE "test*"

Highlighting
OrientDB uses the Lucene's highlighter. Highlighting can be configured using the metadata JSON. The highlighted content of a field is
returned in a dedicated field suffixed with _hl:

208

Lucene Full Text
SELECT name, $name_hl, description, $description_hl FROM City
WHERE SEARCH_CLASS("+name:cas*

+description:beautiful", {

"highlight": {
"fields": ["name", "description"],
"start": "",
"end": ""
}
}) = true

Parameters
fields: array of field names to be highlighted
start: start delimiter for highlighted text (default \)
end: end delimiter for highlighted text (default \)
maxNumFragments: maximum number of text's fragments to highlight

Sorting
Documents retrieved by a search call are ordered by their score. It is possible to configure the way the document are sorted. Read
carefully the official documentation about sorting : https://lucene.apache.org/core/6_6_1/core/org/apache/lucene/search/Sort.html
SELECT name, description, size FROM City
WHERE SEARCH_CLASS("+name:cas*

+description:beautiful", {

"sort": [ { 'field': 'size', reverse:true, type:'INT' }]
}) = true

Sort over multiple fields is possible:
SELECT name, description, size FROM City
WHERE SEARCH_CLASS("+name:cas*

+description:beautiful", {

"sort": [
{ 'field': 'size', reverse:true, type:'INT' },
{ 'field': 'name', reverse:false, type:'STRING' },
{ reverse:false, type:'DOC' },
]
}) = true

Sort configuraton:
field: is the field name. Could be absent only if the sort type is DOC or INDEX
reverse: if set to true, will sort for the given field in reverse order
type: look to https://lucene.apache.org/core/6_6_1/core/org/apache/lucene/search/SortField.Type.html
CUSTOM type is not supported

Cross class search (Enterprise Edition)
Bundled with the enterprise edition there's the SEARH_CROSS function that is able to search over all the Lucene indexes defined on a
database
Suppose to define two indexes:
CREATE INDEX Song.title ON Song (title,author) FULLTEXT ENGINE LUCENE METADATA
CREATE INDEX Author.name on Author(name,score) FULLTEXT ENGINE LUCENE METADATA

Searching for a term on each class implies a lot of different queries to be aggregated.
The SEARCH_CLASS function automatically performs the given query on each full-text index configured inside the database.
SELECT

EXPAND(SEARCH_CROSS('beautiful'))

209

Lucene Full Text
The query will be execute over all the indexes configured on each field. It is possible to search over a given field of a certain class, just
qualify the field names with their class name:
SELECT

EXPAND(SEARCH_CROSS('Song.title:beautiful

Author.name:bob'))

Another way is to use the metadata field _CLASS present in every index:
SELECT expand(SEARCH_CROSS('(+_CLASS:Song +title:beautiful) (+_CLASS:Author +name:bob)') )

All the options of a Lucene's query are allowed: inline boosting, phrase queries, proximity etc.
The function accepts a metadata JSON as second parameter:
SELECT

EXPAND(SEARCH_CROSS('Author.name:bob Song.title:*tain', {"

"allowLeadingWildcard" : true,
"boost": {
"Author.name": 2.0
}
}
)

Highlight isn't supported yet.

Lucene Writer fine tuning (expert)
It is possible to fine tune the behaviour of the underlying Lucene's IndexWriter
CREATE INDEX City.name ON City(name)
FULLTEXT ENGINE LUCENE METADATA {
"directory_type": "nio",
"use_compound_file": false,
"ram_buffer_MB": "16",
"max_buffered_docs": "-1",
"max_buffered_delete_terms": "-1",
"ram_per_thread_MB": "1024",
"default": "org.apache.lucene.analysis.standard.StandardAnalyzer"
}

directory_type: configure the acces type to the Lucene's index
nio (default): the index is opened with NIOFSDirectory
mmap: the index is opened with MMapDirectory
ram: index will be created in memory with RAMDirectory
use_compound_file: default is false
ram_buffer_MB: size of the document's buffer in M B, default value is 16 M B (which means flush when buffered docs consume
approximately 16 M B RAM )
max_buffered_docs: size of the document's buffer in number of docs, disabled by default (because IndexWriter flushes by RAM
usage by default)
max_buffered_delete_terms: disabled by default (because IndexWriter flushes by RAM usage by default).
ram_per_thread_MB: default value is 1945
For a detailed explanation of config parameters and IndexWriter behaviour
indexWriterConfig : https://lucene.apache.org/core/6_6_0/core/org/apache/lucene/index/IndexWriterConfig.html
indexWriter: https://lucene.apache.org/core/6_6_0/core/org/apache/lucene/index/IndexWriter.html

Index lifecycle
Lucene indexes are lazy. If the index is in idle mode, no reads and no writes, it will be closed. Intervals are fully configurable.
flushIndexInterval: flushing index interval in milliseconds, default to 20000 (10s)

210

Lucene Full Text
closeAfterInterval: closing index interval in milliseconds, default to 120000 (12m)
firstFlushAfter: first flush time in milliseconds, default to 10000 (10s)
To configure the index lifecycle, just pass the parameters in the JSON of metadata:
CREATE INDEX City.name ON City(name) FULLTEXT ENGINE LUCENE METADATA
{
"flushIndexInterval": 200000,
"closeAfterInterval": 200000,
"firstFlushAfter": 20000
}

Create index using the Java API
The FullText Index with the Lucene Engine is configurable through the Java API.
OSchema schema = databaseDocumentTx.getMetadata().getSchema();
OClass oClass = schema.createClass("Foo");
oClass.createProperty("name", OType.STRING);
oClass.createIndex("City.name", "FULLTEXT", null, null, "LUCENE", new String[] { "name"});

The LUCENE operator (deprecated)
NOTE: LUCENE operator is translated to SEARCH_FIELDS function, but it doesn't support the metadata JSON
You can query the Lucene FullText Index using the custom operator

LUCENE

with the Query Parser Syntax from the Lucene Engine.

SELECT FROM V WHERE name LUCENE "test*"

This query searches for

test

,

tests

,

tester

, and so on from the property

name

of the class

V

. The query can use proximity

operator ~, the required (+) and prohibit (-) operators, phrase queries, regexp queries:

SELECT FROM Article WHERE content LUCENE "(+graph -rdbms) AND +cloud"

Working with multiple fields (deprecated)
NOTE: define a single Lucene index on the class and use SEARCH_CLASS function
In addition to the standard Lucene query above, you can also query multiple fields. For example,

SELECT FROM Class WHERE [prop1, prop2] LUCENE "query"

In this case, if the word

query

is a plain string, the engine parses the query using M ultiFieldQueryParser on each indexed field.

To execute a more complex query on each field, surround your query with parentheses, which causes the query to address specific
fields.

SELECT FROM Article WHERE [content, author] LUCENE "(content:graph AND author:john)"

Here, the engine parses the query using the QueryParser

Creating a Manual Lucene Index (deprecated)
NOTE: avoid manual Lucene index
The Lucene Engine supports index creation without the need for a class.
S yntax:

211

Lucene Full Text
CREATE INDEX

FULLTEXT ENGINE LUCENE

[] [METADATA {}]

For example, create a manual index using the

CREATE INDEX

command:

CREATE INDEX Manual FULLTEXT ENGINE LUCENE STRING, STRING

Once you have created the index

Manual

, you can insert values in index using the

INSERT INTO INDEX:...

command.

INSERT INTO INDEX:Manual (key, rid) VALUES(['Enrico', 'Rome'], #5:0)

You can then query the index through

SELECT...FROM INDEX:

:

SELECT FROM INDEX:Manual WHERE key LUCENE "Enrico"

M anual indexes could be created programmatically using the Java API
ODocument meta = new ODocument().field("analyzer", StandardAnalyzer.class.getName());
OIndex index = databaseDocumentTx.getMetadata().getIndexManager()
.createIndex("apiManual", OClass.INDEX_TYPE.FULLTEXT.toString(),
new OSimpleKeyIndexDefinition(1, OType.STRING, OType.STRING), null, null, meta, OLuceneIndexFactory.LUCENE_ALGORITHM)
;

212

Lucene Spatial Index

Lucene Spatial
(Versions 2.2 and after only, otherwise look at Legacy section)
This module is provided as external plugin. You can find it bundled in the GeoSpatial distribution, or you can add this plugin by yourself
into any OrientDB distribution (Community and Enterprise Editions).

Install
Download the plugin jar from maven central:
http://central.maven.org/maven2/com/orientechnologies/orientdb-spatial/3.0.0RC1/orientdb-spatial-3.0.0RC1-dist.jar

After download, copy the jar to OrientDB lib directory (please make sure that the version of your OrientDB server and the version of
the plugin are the same. Upgrade your OrientDB server, if necessary). On *nix system it could be done this way:
wget http://central.maven.org/maven2/com/orientechnologies/orientdb-spatial/3.0.0RC1/orientdb-spatial-3.0.0RC1-dist.jar
cp orientdb-spatial-3.0.0RC1-dist.jar /PATH/orientdb-community-3.0.0RC1/lib/

OrientDB will load the spatial plugin on startup.

Geometry Data
OrientDB supports the following Geometry objects :
Point (OPoint)
Line (OLine)
Polygon (OPolygon)
M ultiPoint (OMultiPoint)
M ultiLine (OMultiline)
M ultiPolygon (OMultiPlygon)
Geometry Collections
OrientDB stores those objects like embedded documents with special classes. The module creates abstract classes that represent each
Geometry object type, and those classes can be embedded in user defined classes to provide geospatial information.
Each spatial classes (Geometry Collection excluded) comes with field coordinates that will be used to store the geometry structure. The
"coordinates" field of a geometry object is composed of one position (Point), an array of positions (LineString or M ultiPoint), an array
of arrays of positions (Polygons, M ultiLineStrings) or a multidimensional array of positions (M ultiPolygon).

Geometry data Example
Restaurants Domain
CREATE class Restaurant
CREATE PROPERTY Restaurant.name STRING
CREATE PROPERTY Restaurant.location EMBEDDED OPoint

To insert restaurants with location
From SQL
INSERT INTO

Restaurant SET name = 'Dar Poeta', location = {"@class": "OPoint","coordinates" : [12.4684635,41.8914114]}

or as an alternative, if you use WKT format you can use the function

ST_GeomFromText

to create the OrientDB geometry object.

213

Lucene Spatial Index
INSERT INTO

Restaurant SET name = 'Dar Poeta', location = St_GeomFromText("POINT (12.4684635 41.8914114)")

From JAVA
ODocument location = new ODocument("OPoint");
location.field("coordinates", Arrays.asList(12.4684635, 41.8914114));
ODocument doc = new ODocument("Restaurant");
doc.field("name","Dar Poeta");
doc.field("location",location);
doc.save();

A spatial index on the location field s defined by
CREATE INDEX Restaurant.location ON Restaurant(location) SPATIAL ENGINE LUCENE"

Functions
OrientDB follows The Open Geospatial Consortium OGC for extending SQL to support spatial data. OrientDB implements a subset of
SQL-M M functions with ST prefix (Spatial Type)

ST_AsText
Syntax : ST_AsText(geom)
Example
SELECT ST_AsText({"@class": "OPoint","coordinates" : [12.4684635,41.8914114]})
Result
---------POINT (12.4684635 41.8914114)

ST_GeomFromText
Syntax : ST_GeomFromText(text)
Example
select ST_GeomFromText("POINT (12.4684635 41.8914114)")
Result
---------------------------------------------------------------------------------{"@type":"d","@version":0,"@class":"OPoint","coordinates":[12.4684635,41.8914114]}

ST_AsGeoJSON
Syntax : ST_AsGeoJSON(geom)
Example
select ST_AsGeoJSON(ST_GeomFromText("POINT (12.4684635 41.8914114)"))
Result
---------{"type":"Point","coordinates":[12.468464,41.891411]}

ST_GeomFromGeoJSON

214

Lucene Spatial Index
Syntax : ST_GeomFromGeoJSON(getJsonText)
Example
select ST_GeomFromGeoJSON('{"type":"Point","coordinates":[12.4684635,41.8914114]}')
Result
---------------------------------------------------------------------------------{"@type":"d","@version":0,"@class":"OPoint","coordinates":[12.4684635,41.8914114]}

### ST_Equals
Returns true if geom1 is spatially equal to geom2
Syntax : ST_Equals(geom1,geom2)
Example
```SQL
SELECT ST_Equals(ST_GeomFromText('LINESTRING(0 0, 10 10)'), ST_GeomFromText('LINESTRING(0 0, 5 5, 10 10)'))
Result
----------true

ST_Within
Returns true if geom1 is inside geom2
Syntax : ST_Within(geom1,geom2)
This function will use an index if available.
Example
select * from City where

ST_WITHIN(location,'POLYGON ((12.314015 41.8262816, 12.314015 41.963125, 12.6605063 41.963125, 12.66

05063 41.8262816, 12.314015 41.8262816))') = true

ST_DWithin
Returns true if the geometries are within the specified distance of one another
Syntax : ST_DWithin(geom1,geom2,distance)
Example
SELECT ST_DWithin(ST_GeomFromText('POLYGON((0 0, 10 0, 10 5, 0 5, 0 0))'), ST_GeomFromText('POLYGON((12 0, 14 0, 14 6, 12 6, 1
2 0))'), 2.0d) as distance

SELECT from Polygon where ST_DWithin(geometry, ST_GeomFromText('POLYGON((12 0, 14 0, 14 6, 12 6, 12 0))'), 2.0) = true

ST_Contains
Returns true if geom1 contains geom2
Syntax : ST_Contains(geom1,geom2)
This function will use an index if available.
Example

215

Lucene Spatial Index
SELECT ST_Contains(ST_Buffer(ST_GeomFromText('POINT(0 0)'),10),ST_GeomFromText('POINT(0 0)'))
Result
---------true

SELECT ST_Contains(ST_Buffer(ST_GeomFromText('POINT(0 0)'),10),ST_Buffer(ST_GeomFromText('POINT(0 0)'),20))
Result
---------false

ST_Disjoint
Returns true if geom1 does not spatially intersects geom2
Syntax: St_Disjoint(geom1,geom2)
This function does not use indexes
Example
SELECT ST_Disjoint(ST_GeomFromText('POINT(0 0)'), ST_GeomFromText('LINESTRING ( 2 0, 0 2 )'));
Result
----------------true

SELECT ST_Disjoint(ST_GeomFromText('POINT(0 0)'), ST_GeomFromText('LINESTRING ( 0 0, 0 2 )'));
Result
----------------false

ST_Intersects
Returns true if geom1 spatially intersects geom2
Syntax: ST_Intersects(geom1,geom2)
Example
SELECT ST_Intersects(ST_GeomFromText('POINT(0 0)'), ST_GeomFromText('LINESTRING ( 2 0, 0 2 )'));
Result
------------false

SELECT ST_Intersects(ST_GeomFromText('POINT(0 0)'), ST_GeomFromText('LINESTRING ( 0 0, 0 2 )'));
Result
------------true

ST_AsBinary
Returns the Well-Known Binary (WKB) representation of the geometry
Syntax : ST_AsBinary(geometry)
Example
SELECT ST_AsBinary(ST_GeomFromText('POINT(0 0)'))

216

Lucene Spatial Index

ST_Envelope
Returns a geometry representing the bounding box of the supplied geometry
Syntax : ST_Envelope(geometry)
Example
SELECT ST_AsText(ST_Envelope(ST_GeomFromText('POINT(1 3)')));
Result
---------POINT (1 3)

SELECT ST_AsText(ST_Envelope(ST_GeomFromText('LINESTRING(0 0, 1 3)')))
Result
----------------------------------POLYGON ((0 0, 0 3, 1 3, 1 0, 0 0))

ST_Buffer
Returns a geometry that represents all points whose distance from this Geometry is less than or equal to distance.
Syntax: ST_Buffer(geometry,distance [,config])
where config is an additional parameter (JSON) that can be use to set:
quadSegs: int -> number of segments used to approximate a quarter circle (defaults to 8).
{
quadSegs : 1
}

endCap : round|flat|square -> endcap style (defaults to "round").
{
endCap : 'square'
}

join : round|mitre|bevel -> join style (defaults to "round")
{
join : 'bevel'
}

mitre : double -> mitre ratio limit (only affects mitered join style).
{
join : 'mitre',
mitre : 5.0
}

Example
SELECT ST_AsText(ST_Buffer(ST_GeomFromText('POINT(100 90)'),50))

SELECT ST_AsText(ST_Buffer(ST_GeomFromText('POINT(100 90)'), 50, { quadSegs : 2 }));

Operators
217

Lucene Spatial Index

A && B
Overlaps operator. Returns true if bounding box of A overlaps bounding box of B. This operator will use an index if available.
Example
CREATE CLASS TestLineString
CREATE PROPERTY TestLineString.location EMBEDDED OLineString
INSERT INTO TestLineSTring SET name = 'Test1' , location = St_GeomFromText("LINESTRING(0 0, 3 3)")
INSERT INTO TestLineSTring SET name = 'Test2' , location = St_GeomFromText("LINESTRING(0 1, 0 5)")
SELECT FROM TestLineString WHERE location && "LINESTRING(1 2, 4 6)"

Spatial Indexes
To speed up spatial search and match condition, spatial operators and functions can use a spatial index if defined to avoid sequential full
scan of every records.
The current spatial index implementation is built upon lucene-spatial.
The syntax for creating a spatial index on a geometry field is :
CREATE INDEX  ON  (geometry-field) SPATIAL ENGINE LUCENE

Legacy
Before v2.2, OrientDB was able to only index Points. Other Shapes like rectangles and polygons are managed starting from v2.2 (look
above). This is the legacy section for databases created before v2.2.

How to create a Spatial Index
The index can be created on a class that has two fields declared as

(

DOUBLE

latitude

,

longitude

) that are the coordinates of the

Point.
For example we have a class

Place

with 2 double fields

latitude

and

longitude

. To create the spatial index on

Place

use this

syntax.
CREATE INDEX Place.l_lon ON Place(latitude,longitude) SPATIAL ENGINE LUCENE

The Index can also be created with the Java Api. Example:
OSchema schema = databaseDocumentTx.getMetadata().getSchema();
OClass oClass = schema.createClass("Place");
oClass.createProperty("latitude", OType.DOUBLE);
oClass.createProperty("longitude", OType.DOUBLE);
oClass.createProperty("name", OType.STRING);
oClass.createIndex("Place.latitude_longitude", "SPATIAL", null, null, "LUCENE", new String[] { "latitude", "longitude" });

How to query the Spatial Index
Two custom operators has been added to query the Spatial Index:
1.

NEAR

2.

WITHIN

: to find all Points near a given location (

latitude

,

longitude

)

: to find all Points that are within a given Shape

NEAR operator
Finds all Points near a given location (

latitude

,

longitude

).

S yntax

218

Lucene Spatial Index
SELECT FROM Class WHERE [,] NEAR [lat,lon]

To specify

maxDistance

we have to pass a special variable in the context:

SELECT FROM Class WHERE [,,$spatial] NEAR [lat,lon,{"maxDistance": distance}]

The

maxDistance

field has to be in kilometers, not radians. Results are sorted from nearest to farthest.

To know the exact distance between your Point and the Points matched, use the special variable in the context $distance.
SELECT *, $distance FROM Class WHERE [,,$spatial] NEAR [lat,lon,{"maxDistance": distance}]

Examples
Let's take the example we have written before. We have a Spatial Index on Class

Place

on properties

latitude

and

longitude

.

Example: How to find the nearest Place of a given point:
SELECT *,$distance FROM Place WHERE [latitude,longitude,$spatial] NEAR [51.507222,-0.1275,{"maxDistance":1}]

WITHIN operator
Finds all Points that are within a given Shape.

The current release supports only Bounding Box shape

S yntax
SELECT FROM Class WHERE [,] WITHIN [ [ ,  ] , [ ,  ] ... ]

Examples
Example with previous configuration:
SELECT * FROM Places WHERE [latitude,longitude] WITHIN [[51.507222,-0.1275],[55.507222,-0.1275]]

This query will return all Places within the given Bounding Box.

219

M anaging Dates

Managing Dates
OrientDB treats dates as first class citizens. Internally, it saves dates in the Unix time format. M eaning, it stores dates as a

long

variable, which contains the count in milliseconds since the Unix Epoch, (that is, 1 January 1970).

Date and Datetime Formats
In order to make the internal count from the Unix Epoch into something human readable, OrientDB formats the count into date and
datetime formats. By default, these formats are:
Date Format:

yyyy-MM-dd

Datetime Format:

yyyy-MM-dd HH:mm:ss

In the event that these default formats are not sufficient for the needs of your application, you can customize them through
DATABASE...DATEFORMAT

orientdb>

and

DATETIMEFORMAT

ALTER

commands. For instance,

ALTER DATABASE DATEFORMAT "dd MMMM yyyy"

This command updates the current database to use the English format for dates. That is, 14 Febr 2015.

SQL Functions and Methods
To simplify the management of dates, OrientDB SQL automatically parses dates to and from strings and longs. These functions and
methods provide you with more control to manage dates:
S QL

Description

DATE()

Function converts dates to and from strings and dates, also uses custom formats.

SYSDATE()

Function returns the current date.

.format()

M ethod returns the date in different formats.

.asDate()

M ethod converts any type into a date.

.asDatetime()

M ethod converts any type into datetime.

.asLong()

M ethod converts any date into long format, (that is, Unix time).

For example, consider a case where you need to extract only the years for date entries and to arrange them in order. You can use the
.format()

method to extract dates into different formats.

orientdb>

SELECT @RID, id, date.format('yyyy') AS year FROM Order

--------+----+------+
@RID

| id | year |

--------+----+------+
#31:10 | 92 | 2015 |
#31:10 | 44 | 2014 |
#31:10 | 32 | 2014 |
#31:10 | 21 | 2013 |
--------+----+------+

In addition to this, you can also group the results. For instance, extracting the number of orders grouped by year.

220

M anaging Dates

orientdb>

SELECT date.format('yyyy') AS Year, COUNT(*) AS Total

FROM Order ORDER BY Year

------+--------+
Year |

Total |

------+--------+
2015 |

1 |

2014 |

2 |

2013 |

1 |

------+--------+

Dates before 1970
While you may find the default system for managing dates in OrientDB sufficient for your needs, there are some cases where it may not
prove so. For instance, consider a database of archaeological finds, a number of which date to periods not only before 1970 but possibly
even before the Common Era. You can manage this by defining an era or epoch variable in your dates.
For example, consider an instance where you want to add a record noting the date for the foundation of Rome, which is traditionally
referred to as April 21, 753 BC. To enter dates before the Common Era, first run the [
the

GG

ALTER DATABASE DATETIMEFORMAT

] command to add

variable to use in referencing the epoch.

orientdb>

ALTER DATABASE DATETIMEFORMAT "yyyy-MM-dd HH:mm:ss GG"

Once you've run this command, you can create a record that references date and datetime by epoch.
orientdb>

CREATE VERTEX V SET city = "Rome", date = DATE("0753-04-21 00:00:00 BC")

orientdb>

SELECT @RID, city, date FROM V

-------+------+------------------------+
@RID

| city | date

|

-------+------+------------------------+
#9:10 | Rome | 0753-04-21 00:00:00 BC |
-------+------+------------------------+

Using .format() on Insertion
In addition to the above method, instead of changing the date and datetime formats for the database, you can format the results as you
insert the date.
orientdb>

CREATE VERTEX V SET city = "Rome", date = DATE("yyyy-MM-dd HH:mm:ss GG")

orientdb>

SELECT @RID, city, date FROM V

------+------+------------------------+
@RID | city | date

|

------+------+------------------------+
#9:4 | Rome | 0753-04-21 00:00:00 BC |
------+------+------------------------+

Here, you again create a vertex for the traditional date of the foundation of Rome. However, instead of altering the database, you format
the date field in

CREATE VERTEX

command.

Viewing Unix Time

221

M anaging Dates
In addition to the formatted date and datetime, you can also view the underlying count from the Unix Epoch, using the

asLong()

method for records. For example,
orientdb>

SELECT @RID, city, date.asLong() FROM #9:4

------+------+------------------------+
@RID | city | date

|

------+------+------------------------+
#9:4 | Rome | -85889120400000

|

------+------+------------------------+

M eaning that, OrientDB represents the date of April 21, 753 BC, as -85889120400000 in Unix time. You can also work with dates
directly as longs.
orientdb>

CREATE VERTEX V SET city = "Rome", date = DATE(-85889120400000)

orientdb>

SELECT @RID, city, date FROM V

-------+------+------------------------+
@RID

| city | date

|

-------+------+------------------------+
#9:11 | Rome | 0753-04-21 00:00:00 BC |
-------+------+------------------------+

Use ISO 8601 Dates
According to ISO 8601, Combined date and time in UTC: 2014-12-20T00:00:00. To use this standard change the datetimeformat in the
database:
ALTER DATABASE DATETIMEFORMAT "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"

222

Transactions

Transactions
A transaction comprises a unit of work performed within a database management system (or similar system) against a database, and
treated in a coherent and reliable way independent of other transactions. Transactions in a database environment have two main
purposes:
to provide reliable units of work that allow correct recovery from failures and keep a database consistent even in cases of system
failure, when execution stops (completely or partially) and many operations upon a database remain uncompleted, with unclear
status
to provide isolation between programs accessing a database concurrently. If this isolation is not provided, the program's outcome
are possibly erroneous.
A database transaction, by definition, must be atomic, consistent, isolated and durable. Database practitioners often refer to these
properties of database transactions using the acronym ACID. --- Wikipedia
OrientDB is an ACID compliant DBM S.
NOTE: OrientDB keeps the transaction on client RAM , so the transaction size is affected by the available RAM (Heap
memory) on JVM . For transactions involving many records, consider to split it in multiple transactions.

ACID properties
Atomicity
"Atomicity requires that each transaction is 'all or nothing': if one part of the transaction fails, the entire transaction fails, and the
database state is left unchanged. An atomic system must guarantee atomicity in each and every situation, including power failures,
errors, and crashes. To the outside world, a committed transaction appears (by its effects on the database) to be indivisible ("atomic"),
and an aborted transaction does not happen." - WikiPedia

Consistency
"The consistency property ensures that any transaction will bring the database from one valid state to another. Any data written to the
database must be valid according to all defined rules, including but not limited to constraints, cascades, triggers, and any combination
thereof. This does not guarantee correctness of the transaction in all ways the application programmer might have wanted (that is the
responsibility of application-level code) but merely that any programming errors do not violate any defined rules." - WikiPedia
OrientDB uses the M VCC to assure consistency. The difference between the management of M VCC on transactional and nottransactional cases is that with transactional, the exception rollbacks the entire transaction before to be caught by the application.
Look at this example:
S equence

Client/Thread 1

1

Begin of Transaction

2

read(x)

Client/Thread 2

Version of record X

10

3

Begin of Transaction

4

read(x)

10

5

write(x)

10

6

commit

10 -> 11

7

write(x)

10

8

commit

10 -> 11 = Error, in database x already is at 11

Isolation

223

Transactions
"The isolation property ensures that the concurrent execution of transactions results in a system state that would be obtained if
transactions were executed serially, i.e. one after the other. Providing isolation is the main goal of concurrency control. Depending on
concurrency control method, the effects of an incomplete transaction might not even be visible to another transaction." - WikiPedia
OrientDB has different levels of isolation based on settings and configuration:
READ COMMITTED

, the default and the only one available with

REPEATABLE READS
COMMITTED

, allowed only with

plocal

and

memory

remote

protocol

protocols. This mode consumes more memory than

READ

, because any read, query, etc. keep the records in memory to assure the same copy on further access

To change default Isolation Level, use the Java API:
db.begin()
db.getTransaction().setIsolationLevel(OTransaction.ISOLATION_LEVEL.REPEATABLE_READ);

Using

remote

access all the commands are executed on the server, so out of transaction scope. Look below for more information.

Look at this examples:
S equence

Client/Thread 1

1

Begin of Transaction

2

read(x)

Client/Thread 2

3

Begin of Transaction

4

read(x)

5

write(x)

6

commit

7

read(x)

8

commit

At operation 7 the client 1 continues to read the same version of x read in operation 2.
S equence

Client/Thread 1

1

Begin of Transaction

2

read(x)

Client/Thread 2

3

Begin of Transaction

4

read(y)

5

write(y)

6

commit

7

read(y)

8

commit

At operation 7 the client 1 reads the version of y which was written at operation 6 by client 2. This is because it never reads y before.
Breaking of ACID properties when using remote protocol and Commands (S QL, Gremlin, JS , etc)
Transactions are client-side only until the commit. This means that if you're using the "remote" protocol the server can't see local
changes.

224

Transactions

In this scenario you can have different isolation levels with commands. This issue will be solved with OrientDB v3.0 where the
transaction will be flushed to the server before to execute the command.

Durability
"Durability means that once a transaction has been committed, it will remain so, even in the event of power loss, crashes, or errors. In a
relational database, for instance, once a group of SQL statements execute, the results need to be stored permanently (even if the database
crashes immediately thereafter). To defend against power loss, transactions (or their effects) must be recorded in a non-volatile
memory." - WikiPedia

Fail-over
An OrientDB instance can fail for several reasons:
HW problems, such as loss of power or disk error
SW problems, such as a Operating System crash
Application problem, such as a bug that crashes your application that is connected to the Orient engine.
You can use the OrientDB engine directly in the same process of your application. This gives superior performance due to the lack of
inter-process communication. In this case, should your application crash (for any reason), the OrientDB Engine also crashes.
If you're using an OrientDB Server connected remotely, if your application crashes the engine continue to work, but any pending
transaction owned by the client will be rolled back.

Auto-recovery
At start-up the OrientDB Engine checks to if it is restarting from a crash. In this case, the auto-recovery phase starts which rolls back all
pending transactions.
OrientDB has different levels of durability based on storage type, configuration and settings.

Transaction types
No Transaction
Default mode. Each operation is executed instantly.
Calls to

begin()

,

commit()

and

rollback()

have no effect.

Optimistic Transaction
225

Transactions
This mode uses the well known M ulti Version Control System (M VCC) by allowing multiple reads and writes on the same records. The
integrity check is made on commit. If the record has been saved by another transaction in the interim, then an
OConcurrentM odificationException will be thrown. The application can choose either to repeat the transaction or abort it.
NOTE: OrientDB keeps the transaction on client RAM , so the transaction size is affected by the available RAM (Heap)
memory on JVM . For transactions involving many records, consider to split it in multiple transactions.
With Graph API transaction begins automatically, with Document API is explicit by using the

begin()

method. With Graphs you can

change the consistency level.
Example with Document API:
db.open("remote:localhost:7777/petshop");
try{
db.begin(TXTYPE.OPTIMISTIC);
...
// WRITE HERE YOUR TRANSACTION LOGIC
...
db.commit();
}catch( Exception e ){
db.rollback();
} finally{
db.close();
}

In Optimistic transaction new records take temporary Record IDs to avoid to ask to the server a new Record ID every time. Temporary
Record IDs have Cluster Id -1 and Cluster Position < -1. When a new transaction begun the counter is reset to -1:-2. So if you create 3
new records you'll have:
-1:-2
-1:-3
-1:-4
At commit time, these temporary records Record IDs will be converted in the final ones.

Pessimistic Transaction
This mode is not yet supported by the engine.

Nested transactions and propagation
OrientDB doesn't support nested transaction. If further

begin()

are called after a transaction is already begun, then the current

transaction keeps track of call stack to let to the final commit() call to effectively commit the transaction. Look at Transaction
Propagation more information.

Record IDs
OrientDB uses temporary Record ID's with transaction as scope that will be transformed to finals once the transactions is successfully
committed to the database. This avoid to ask for a free slot every time a client creates a record.

Tuning
In some situations transactions can improve performance, typically in the client/server scenario. If you use an Optimistic Transaction,
the OrientDB engine optimizes the network transfer between the client and server, saving both CPU and bandwidth.
For further information look at Transaction tuning to know more.

Distributed environment
226

Transactions
Transactions can be committed across a distributed architecture. Look at Distributed Transactions for more information.

227

Embedding the Server

Embed the Server
Embedding an OrientDB Server inside a Java application has several advantages and interesting features:
Java application that runs embedded with the server can bypass the remote connection and use the database directly with local
mode. local and remote connections against the same database can work in concurrency: OrientDB will synchronize the access.
You can use the Console to control it
You can use the OrientDB Studio
You can replicate the database across distributed standalone or embedded servers
To embed an OrientDB Server inside a Java application you have to create the

OServer

object and use a valid configuration for it.

Requirements
In order to embed the server you need to include the following jar files in the classpath:
orientdb-enterprise-**.jar
orientdb-server-**.jar

Starting from version 2.2, please set the

MaxDirectMemorySize

parameter. Setting this parameter is required. You can set it to a very high

value, e.g. 512g (JVM setting):
-XX:MaxDirectMemorySize=512g

Setting

MaxDirectMemorySize

to a very high value should not concern you as it does not mean that OrientDB will consume all 512GB of

memory. The size of direct memory consumed by OrientDB is limited by the size of the disk cache (variable
storage.diskCache.bufferSize

).

When you start the Server using the provided

server.sh

But when you embed the Server it is required that you set
Note: if you are using a pom file, you may set

or

server.bat

scripts,

MaxDirectMemorySize

MaxDirectMemorySize

MaxDirectMemorySize

is set already by those scripts.

manually.

inside your pom in the following way:


-XX:MaxDirectMemorySize=512g


If you start an embedded Server without setting this variable you will get a WARNING message similar to the following:
MaxDirectMemorySize JVM option is not set or has invalid value, that may cause out of memory errors

Include the commands you need
Even if most of the HTTP commands are auto registered assure to have all the commands you need. For example the static content must
be registered. This is fundamental if you want to use OrientDB as Web Server providing static content like the Studio app:

228

Embedding the Server











Use an embedded configuration
import com.orientechnologies.orient.server.OServerMain;
public class OrientDBEmbeddable {
public static void main(String[] args) throws Exception {
OServer server = OServerMain.create();
server.startup(
""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
//The following is required to eliminate an error or warning "Error on resolving property: ORIENTDB_HOME"
+ ""
+ "" + "");
server.activate();
}
}

Once the embedded server is running, clients can connect using the remote connection method. For example in the console, you can
connect with:
connect remote:localhost:{port}/{db} {user} {password}
where:
port

: the port that the binary server listens on

db

: the database name to connect to (defaults to "db" and can be set using  in the configuration
user

: the user to connect with (this is NOT the same as root user in the configuration)

password : the user to connect with (this is NOT the same as root password in the configuration)

Use custom file for configuration
229

Embedding the Server
Use a regular

File

:

public class OrientDBEmbeddable {
public static void main(String[] args) throws Exception {
OServer server = OServerMain.create();
server.startup(new File("/usr/local/temp/db.config"));
server.activate();
}
}

Use a stream for configuration
Use an

InputStream

from the class loader:

public class OrientDBEmbeddable {
public static void main(String[] args) throws Exception {
OServer server = OServerMain.create();
server.startup(getClass().getResourceAsStream("db.config"));
server.activate();
}
}

Use a OServerConfiguration object for configuration
Or an

InputStream

from the class loader:

public class OrientDBEmbeddable {
public static void main(String[] args) throws Exception {
OServer server = OServerMain.create();
OServerConfiguration cfg = new OServerConfiguration();
// FILL THE OServerConfiguration OBJECT
server.startup(cfg);
server.activate();
}
}

Shutdown
OrientDB Server creates some threads internally as non-daemon, so they run even if the main application exits. Use the
OServer.shutdown()

method to shutdown the server in soft way:

import com.orientechnologies.orient.server.OServerMain;
public class OrientDBEmbeddable {
public static void main(String[] args) throws Exception {
OServer server = OServerMain.create();
server.startup(new File("/usr/local/temp/db.config"));
server.activate();
...
server.shutdown();
}
}

Setting ORIENTDB_HOME
Some functionality wil not work properly if the system property 'ORIENTDB_HOM E' is not set. You can set it programmatically like
this:

230

Embedding the Server
import com.orientechnologies.orient.server.OServerMain;
public class OrientDBEmbeddable {
public static void main(String[] args) throws Exception {
String orientdbHome = new File("").getAbsolutePath(); //Set OrientDB home to current directory
System.setProperty("ORIENTDB_HOME", orientdbHome);
OServer server = OServerMain.create();
server.startup(cfg);
server.activate();
}
}

231

Available OrientDB Plugins

OrientDB Plugins
The OrientDB Server is a customizable platform to build powerful server component and applications.
Since the OrientDB server contains an integrated Web Server what about creating server side applications without the need to have a
J2EE and Servlet container? By extending the server you can benefit of the best performance because you don't have many layers but
the database and the application reside on the same JVM without the cost of the network and serialization of requests.
Furthermore you can package your application together with the OrientDB server to distribute just a ZIP file containing the entire
Application, Web server and Database.
To customize the OrientDB server you have two powerful tools:
Handlers
Custom commands
To debug the server while you develop new feature follow Debug the server.

Handlers (Server Plugins)
Handlers are plug-ins and starts when OrientDB starts.
To create a new handler create the class and register it in the OrientDB server configuration.

Create the Handler class
A Handler must implements the OServerPlugin interface or extends the OServerPluginAbstract abstract class.
Below an example of a handler that print every 5 seconds a message if the "log" parameters has been configured to be "true":
package orientdb.test;
public class PrinterHandler extends OServerPluginAbstract {
private boolean

log = false;

@Override
public void config(OServer oServer, OServerParameterConfiguration[] iParams) {
for (OServerParameterConfiguration p : iParams) {
if (p.name.equalsIgnoreCase("log"))
log = true;
}
Orient.getTimer().schedule( new TimerTask() {
@Override
public void run() {
if( log )
System.out.println("It's the PrinterHandler!");
}
}, 5000, 5000);
}
@Override
public String getName() {
return "PrinterHandler";
}
}

Register the handler
Once created, register it to the server configuration in orientdb-server-config.xml file:

232

Available OrientDB Plugins








...

Note that you can specify arbitrary parameters in form of name and value. Those parameters can be read by the config() method. In this
example a parameter "log" is read. Look upon to the example of handler to know how to read parameters specified in configuration.

Steps to register a function as a Plugin in OrientDB
In this case we'll create a plugin that only registers one function in OrientDB: pow (returns the value of the first argument raised to the
power of the second argument). We'll also support M odular exponentiation.
The syntax will be

pow(,  [, ])

.

you should have a directory structure like this
.
├─ src
|

└─ main

|

├─ assembly

|

|

|

├─ java

|

|

|

|

|

|

|

└─ resources

└─ assembly.xml
└─ com
└─ app
└─ OPowPlugin.java

|

└─ plugin.json

|
└─ pom.xml

OPowPlugin.java
package com.app;
import com.orientechnologies.common.log.OLogManager;
import com.orientechnologies.orient.core.command.OCommandContext;
import com.orientechnologies.orient.core.db.record.OIdentifiable;
import com.orientechnologies.orient.core.sql.OSQLEngine;
import com.orientechnologies.orient.core.sql.functions.OSQLFunctionAbstract;
import com.orientechnologies.orient.server.OServer;
import com.orientechnologies.orient.server.config.OServerParameterConfiguration;
import com.orientechnologies.orient.server.plugin.OServerPluginAbstract;
import java.util.ArrayList;
import java.util.List;
public class OPowPlugin extends OServerPluginAbstract {
public OPowPlugin() {
}
@Override
public String getName() {
return "pow-plugin";
}
@Override
public void startup() {
super.startup();
OSQLEngine.getInstance().registerFunction("pow", new OSQLFunctionAbstract("pow", 2, 3) {
@Override
public String getSyntax() {
return "pow(,  [, ])";
}

233

Available OrientDB Plugins
@Override
public Object execute(Object iThis, OIdentifiable iCurrentRecord, Object iCurrentResult, final Object[] iParams, O
CommandContext iContext) {
if (iParams[0] == null || iParams[1] == null) {
return null;
}
if (!(iParams[0] instanceof Number) || !(iParams[1] instanceof Number)) {
return null;
}
final long base = ((Number) iParams[0]).longValue();
final long power = ((Number) iParams[1]).longValue();
if (iParams.length == 3) { // modular exponentiation
if (iParams[2] == null) {
return null;
}
if (!(iParams[2] instanceof Number)) {
return null;
}
final long mod = ((Number) iParams[2]).longValue();
if (power < 0) {
OLogManager.instance().warn(this, "negative numbers as exponent are not supported");
}
return modPow(base, power, mod);
}
return power > 0 ? pow(base, power) : 1D / pow(base, -power);
}
});
OLogManager.instance().info(this, "pow function registered");
}
private double pow(long base, long power) {
double r = 1;
List bits = bits(power);
for (int i = bits.size() - 1; i >= 0; i--) {
r *= r;
if (bits.get(i)) {
r *= base;
}
}
return r;
}
private double modPow(long base, long power, long mod) {
double r = 1;
List bits = bits(power);
for (int i = bits.size() - 1; i >= 0; i--) {
r = (r * r) % mod;
if (bits.get(i)) {
r = (r * base) % mod;
}
}
return r;
}
private List bits(long n) {
List bits = new ArrayList();
while (n > 0) {
bits.add(n % 2 == 1);
n /= 2;
}
return bits;
}
@Override
public void config(OServer oServer, OServerParameterConfiguration[] iParams) {
}
@Override

234

Available OrientDB Plugins
public void shutdown() {
super.shutdown();
}
}

pom.xml


4.0.0
com.app
pow-plugin
2.0.7
jar
pow-plugin

2.0.7




maven-assembly-plugin
2.4


src/main/assembly/assembly.xml




make-assembly

package


single






org.apache.maven.plugins
maven-compiler-plugin
3.1







com.orientechnologies
orientdb-core
${orientdb.version}
compile


com.orientechnologies
orientdb-server
${orientdb.version}
compile




assembly.xml

235

Available OrientDB Plugins

dist

jar

false



true

${groupId}:${artifactId}





plugin.json
{
"name" : "pow-plugin",
"version" : "2.0.7",
"javaClass": "com.app.OPowPlugin",
"parameters" : {},
"description" : "The Pow Plugin",
"copyrights" : "No copyrights"
}

Build the project and then:
cp target/pow-plugin-2.0.7-dist.jar $ORIENTDB_HOME/plugins/

You should see the following in OrientDB server log:
INFO

Installing dynamic plugin 'pow-plugin-2.0.7-dist.jar'... [OServerPluginManager]

INFO

pow function registered [OPowPlugin]

And now you can:
orientdb {db=Pow}> select pow(2,10)
----+------+-----#

|@CLASS|pow

----+------+-----0

|null

|1024.0

----+------+-----orientdb {db=Pow}> select pow(2,10,5)
----+------+---#

|@CLASS|pow

----+------+---0

|null

|4.0

----+------+----

This small project is available here.

Creating a distributed change manager
As more complete example let's create a distributed record manager by installing hooks to all the server's databases and push these
changes to the remote client caches.

236

Available OrientDB Plugins
public class DistributedRecordHook extends OServerHandlerAbstract implements ORecordHook {
private boolean log = false;
@Override
public void config(OServer oServer, OServerParameterConfiguration[] iParams) {
for (OServerParameterConfiguration p : iParams) {
if (p.name.equalsIgnoreCase("log"))
log = true;
}
}
@Override
public void onAfterClientRequest(final OClientConnection iConnection, final byte iRequestType) {
if (iRequestType == OChannelBinaryProtocol.REQUEST_DB_OPEN)
iConnection.database.registerHook(this);
else if (iRequestType == OChannelBinaryProtocol.REQUEST_DB_CLOSE)
iConnection.database.unregisterHook(this);
}
@Override
public boolean onTrigger(TYPE iType, ORecord iRecord) {
try {
if (log)
System.out.println("Broadcasting record: " + iRecord + "...");
OClientConnectionManager.instance().broadcastRecord2Clients((ORecordInternal) iRecord, null);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
@Override
public String getName() {
return "DistributedRecordHook";
}
}

Custom commands
Custom commands are useful when you want to add behavior or business logic at the server side.
A Server command is a class that implements the OServerCommand interface or extends one of the following abstract classes:
OServerCommandAuthenticatedDbAbstract if the command requires an authentication at the database
OServerCommandAuthenticatedServerAbstract if the command requires an authentication at the server

The Hello World Web
To learn how to create a custom command, let's begin with a command that just returns "Hello world!".
OrientDB follows the convention that the command name is:
OServerCommand

Where:

method is the HTTP method and can be: GET, POST, PUT, DELETE
name is the command name
In our case the class name will be "OServerCommandGetHello". We want that the use must be authenticated against the database to
execute it as any user.
Furthermore we'd like to receive via configuration if we must display the text in Italic or not, so for this purpose we'll declare a
parameter named "italic" of type boolean (true or false).

237

Available OrientDB Plugins
package org.example;
public class OServerCommandGetHello extends OServerCommandAuthenticatedDbAbstract {
// DECLARE THE PARAMETERS
private boolean italic = false;
public OServerCommandGetHello(final OServerCommandConfiguration iConfiguration) {
// PARSE PARAMETERS ON STARTUP
for (OServerEntryConfiguration par : iConfiguration.parameters) {
if (par.name.equals("italic")) {
italic = Boolean.parseBoolean(par.value);
}
}
}
@Override
public boolean execute(final OHttpRequest iRequest, OHttpResponse iResponse) throws Exception {
// CHECK THE SYNTAX. 3 IS THE NUMBER OF MANDATORY PARAMETERS
String[] urlParts = checkSyntax(iRequest.url, 3, "Syntax error: hello//");
// TELLS TO THE SERVER WHAT I'M DOING (IT'S FOR THE PROFILER)
iRequest.data.commandInfo = "Salutation";
iRequest.data.commandDetail = "This is just a test";
// GET THE PARAMETERS
String name = urlParts[2];
// CREATE THE RESULT
String result = "Hello " + name;
if (italic) {
result = "" + result + "";
}
// SEND BACK THE RESPONSE AS TEXT
iResponse.send(OHttpUtils.STATUS_OK_CODE, "OK", null, OHttpUtils.CONTENT_TEXT_PLAIN, result);
// RETURN ALWAYS FALSE, UNLESS YOU WANT TO EXECUTE COMMANDS IN CHAIN
return false;
}
@Override
public String[] getNames() {
return new String[]{"GET|hello/* POST|hello/*"};
}
}

Once created the command you need to register them through the orientdb-server-config.xml file. Put a new tag
tag

commands

of



with attribute

protocol="http"



under the

:

...










Where:
implementation is the full class name of the command
pattern is how the command is called in the format:
URL:

|

. In this case it's executed on HTTP GET with the

/

parameters specify parameters to pass to the command on startup
entry is the parameter pair name/value
To test it open a browser at this address:

238

Available OrientDB Plugins
http://localhost/hello/demo/Luca

You will see:
Hello Luca

Complete example
Below a more complex example taken by official distribution. It is the command that executes queries via HTTP. Note how to get a
database instance to execute operation against the database:
public class OServerCommandGetQuery extends OServerCommandAuthenticatedDbAbstract {
private static final String[] NAMES = { "GET|query/*" };
@Override
public boolean execute(OHttpRequest iRequest, OHttpResponse iResponse) throws Exception {
String[] urlParts = checkSyntax(
iRequest.url,
4,
"Syntax error: query//sql/[/][/].
Limit is optional and is setted to 20 by default. Set expressely to 0 to have no limits."); int limit = urlParts.length > 4 ? Integer.parseInt(urlParts[4]) : 20; String fetchPlan = urlParts.length > 5 ? urlParts[5] : null; String text = urlParts[3]; iRequest.data.commandInfo = "Query"; iRequest.data.commandDetail = text; ODatabaseDocumentTx db = null; List response; try { db = getProfiledDatabaseInstance(iRequest); response = (List) db.command(new OSQLSynchQuery(text, limit).setFetchPlan(fetchPlan)).exec ute(); } finally { if (db != null) { db.close(); } } iResponse.writeRecords(response, fetchPlan); return false; } @Override public String[] getNames() { return NAMES; } } Include JARS in the classpath If your extensions need additional libraries put the additional jar files under the /lib folder of the server installation. Debug the server To debug your plugin you can start your server in debug mode. 239 Available OrientDB Plugins Parameter M ain class JVM parameters Value com.orientechnologies.orient.server.OServerMain -server -DORIENTDB_HOME=/opt/orientdb -Dorientdb.www.path=src/site Djava.util.logging.config.file=${ORIENTDB_HOME}/config/orientdb-server-log.properties Dorientdb.config.file=${ORIENTDB_HOME}/config/orientdb-server-config.xml 240 Automatic Backup Automatic Backup Server Plugin Using this server plugin, OrientDB executes regular backups on the databases. It implements the Java class: com.orientechnologies.orient.server.handler.OAutomaticBackup Plugin Configuration Beginning with version 2.2, OrientDB manages the server plugin configuration from a separate JSON. You can update this file manually or through OrientDB Studio. To enable automatic backups, use the following section in the config/orientdb-server-config.xml configuration file: This section tells the OrientDB server to read the file at $ORIENTDB_HOME/config/automatic-backup.json for the automatic backup configuration. { "enabled": true, "mode": "FULL_BACKUP", "exportOptions": "", "delay": "4h", "firstTime": "23:00:00", "targetDirectory": "backup", "targetFileName": "${DBNAME}-${DATE:yyyyMMddHHmmss}.zip", "compressionLevel": 9, "bufferSize": 1048576 } "enabled" true Defines whether it uses automatic backups. The supported values are: Enables automatic backups. false "mode" Disables automatic backups. This is the default setting. Defines the backup mode. The supported values are: "FULL_BACKUP" Executes a full backup. Prior to version 2.2, this was the only mode available. This operation blocks the database. "INCREMENTAL_BACKUP" Executes an incremental backup. This is available only in the Enterprise Edition. It uses one directory per database. This operation doesn't block the database. "EXPORT" Executes an database export, using gziped JSON format. This operation is not blocking. "exportOptions" "delay" ms Defines export options to use with that mode. This feature was introduced in version 2.2. Defines the delay time for each backup. Supports the following suffixes: Delay measured in milliseconds. s Delay measured in seconds. m Delay measured in minutes. h Delay measured in hours. d Delay measured in days. "firstTime" Defines when to initiate the first backup in the schedule. It uses the format of HH:mm:ss in the GM T time zone, on the current day. "targetDirectory" "targetFileName" backup.zip" Defines the target directory to write backups. By default, it is set to the backup/ directory. Defines the target filename. This parameter supports the use of the following variables, (that is, produces mydatabase-backup.zip "${DBNAME}- ): 241 Automatic Backup Renders the database name. ${DBNAME} Renders the current date, using the Java DateTime syntax format. ${DATE} "dbInclude" Defines in a list the databases to include in the automatic backups. If empty, it backs up all databases. "dbExclude" Defines in a list the databases to exclude from the automatic backups. "bufferSize" Defines the in-memory buffer sizes to use in compression. By default, it is set to 1MB . Larger buffers mean faster backups, but they in turn consume more RAM . "compressionLevel" Defines the compression level for the resulting ZIP file. By default it is set to the maximum level of 9 . Set it to a lower value if you find that the backup takes too much time. Legacy Plugin Configuration In versions prior to 2.2, the only option in configuring automatic backups is to use the config/orientdb-server-config.xml configuration file. Beginning with version 2.2 you can manage automatic backup configuration through a separate JSON file or use the legacy approach. The example below configures automatic backups/exports on the database as a Server Plugin. enabled Defines whether it uses automatic backups. Supported values are: true false Enables automatic backups. Disables automatic backups. This is the default setting. Defines the backup mode. Supported values are: mode/> FULL_BACKUP Executes a full backup. For versions prior to 2.2, this is the only option available. This operation blocks the database. INCREMENTAL_BACKUP Executes an incremental backup. Uses one directory per database. This operation doesn't block the database. * EXPORT Executes an export of the database in gzipped JSON format, instead of a backup. This operation doesn't block the database. exportOptions delay Defines export options to use with that mode. This feature was introduced in version 2.2. Defines the delay time. Supports the following suffixes: ms Delay measured in milliseconds. s Delay measured in seconds. m Delay measured in minutes. h Delay measured in hours. d Delay measured in days. firstTime Defines when to initiate the first backup in the schedule. It uses the format of HH:mm:ss in the GM T time zone, on the current day. target.directory target.fileName Defines the target directory to write backups. By default, it is set to the backup/ directory. Defines the target file name. The parameter supports the use of the following variables, (that is, ${DBNAME} ${DATE} produces a mydatabase-backup.zip file). Renders the database name. Renders the current date, using the Java DateTime syntax format. db.include Defines in a list the databases to include in the automatic backups. If left empty, it backs up all databases. db.exclude Defines in a list the databases to exclude from automatic backups. bufferSize Defines the in-memory buffer sizes to use in compression. By default it is set to 1MB . Larger buffers mean faster backups, but use more RAM . This feature was introduced in version 1.7. compressionLevel Defines the compression level for the resulting ZIP file. By default, it is set to the maximum level of 9 . Set it to a lower value if you find that the backup takes too much time. 243 SysLog SysLog Plugin Java class implementation: com.orientechnologies.security.syslog.ODefaultSyslog Available since: v. 2.2.0. Introduction Allows sending event logs to the Operating System's SYSLOG daemon. Configuration This plugin is configured as a Server plugin. The plugin can be easily configured by changing parameters in the orientdb-server- file.: config.xml Name Description Type Example S ince enabled true to turn on, false (default) is turned off boolean true 2.2.0 debug Enables debug mode boolean false 2.2.0 hostname The hostname of the syslog daemon string localhost 2.2.0 port The UDP port of the syslog daemon integer 514 2.2.0 appName The name of the application submitting the events to SysLog string OrientDB 2.2.0 Default configuration in orientdb-server-config.xml . Example: Usage Look at Security Config. 244 M ail Mail Plugin Java class implementation: com.orientechnologies.orient.server.plugin.mail.OMailPlugin Available since: v. 1.2.0. Introduction Allows to send (and in future read) emails. Configuration This plugin is configured as a Server handler. The plugin can be configured in easy way by changing parameters: Name Description Type true to turn on, false (default) is turned off boolean true 1.2.0 profile..mail.smtp.host The SM TP host name or ip-address string smtp.gmail.com 1.2.0 profile..mail.smtp.port The SM TP port number 587 1.2.0 profile..mail.smtp.auth Authenticate in SM TP boolean true 1.2.0 Enable the starttls boolean true 1.2.0 profile..mail.smtp.user The SM TP username string yoda@starwars.com 1.2.0 profile..mail.from The source's email address string yoda@starwars.com 1.7 The SM TP password string UseTh3F0rc3 1.2.0 The date format to use, default is "yyyy-M M -dd HH:mm:ss" string yyyy-M M -dd HH:mm:ss 1.2.0 enabled profile. .mail.smtp.starttls.enable profile. .mail.smtp.password profile..mail.date.format Example S ince Default configuration in orientdb-server-config.xml. Example: Usage The message is managed as a map of properties containing all the fields those are part of the message. 245 M ail Supported message properties: Name Description Mandatory Example S ince from source email address No to : "first@mail.com", "second@mail.com" 1.7 to destination addresses separated by commas Yes to : "first@mail.com", "second@mail.com" 1.2.0 cc Carbon copy addresses separated by commas No cc: "first@mail.com", "second@mail.com" 1.2.0 bcc Blind Carbon Copy addresses separated by commas No bcc : "first@mail.com", "second@mail.com" 1.2.0 subject The subject of the message No subject : "This Email plugin rocks!" 1.2.0 message The message's content Yes message : "Hi, how are you mate?" 1.2.0 date The subject of the message. Pass a java.util.Date object or a string formatted following the rules specified in "mail.date.format" configuration parameter or "yyyyM M -dd HH:mm:ss" is taken No, if not specified current date is assumed date : "2012-09-25 13:20:00" 1.2.0 attachments The files to attach No 1.2.0 From Server-Side Functions The Email plugin install a new variable in the server-side function's context: "mail". "profile" attribute is the profile name in configuration. Example to send an email writing a function in JS: mail.send({ profile : "default", to: "orientdb@ruletheworld.com", cc: "yoda@starwars.com", bcc: "darthvader@starwars.com", subject: "The EMail plugin works", message : "Sending email from OrientDB Server is so powerful to build real web applications!" }); On Nashorn (>= Java8) the mapping of JSON to M ap is not implicit. Use this: mail.send( new java.util.HashMap{ profile : "default", to: "orientdb@ruletheworld.com", cc: "yoda@starwars.com", bcc: "darthvader@starwars.com", subject: "The EMail plugin works", message : "Sending email from OrientDB Server is so powerful to build real web applications!" }); From Java 246 M ail OMailPlugin plugin = OServerMain.server().getPlugin("mail"); Map message = new HashMap(); message.put("profile", "default"); message.put("to", "orientdb@ruletheworld.com"); message.put("cc", "yoda@starts.com,yoda-beach@starts.com"); message.put("bcc", "darthvader@starwars.com"); message.put("subject", "The EMail plugin works"); message.put("message", "Sending email from OrientDB Server is so powerful to build real web applications!"); plugin.send(message); 247 JM X JMX plugin Java class implementation: com.orientechnologies.orient.server.handler.OJMXPlugin Available since: v. 1.2.0. Introduction Expose the OrientDB server configuration through JM X protocol. This task is configured as a Server handler. The task can be configured in easy way by changing parameters: enabled: true to turn on, false (default) is turned off profilerManaged: manage the Profiler instance Default configuration in orientdb-server-config.xml 248 Rexster Rexster Rexster provides a RESTful shell to any Blueprints-complaint graph database. This HTTP web service provides: a set of standard lowlevel GET, POST, and DELETE methods, a flexible extension model which allows plug-in like development for external services (such as ad-hoc graph queries through Gremlin), and a browser-based interface called The Dog House. A graph database hosted in the OrientDB can be configured in Rexster and then accessed using the standard RESTful interface powered by the Rexster web server. Installation You can get the latest stable release of Rexster from its Download Page. The latest stable release when this page was last updated was 2.5.0. Or you can build a snapshot by executing the following Git and M aven commands: git clone https://github.com/tinkerpop/rexster.git cd rexster mvn clean install Rexster is distributed as a zip file (also the building process creates a zip file) hence the installation consist of unzipping the archive in a directory of your choice. In the following sections, this directory is referred to as $REXSTER_HOME. After unzipping the archive, you should copy orient-client.jar and orient-enterprise.jar in $REXSTER_HOME/ext. M ake sure you use the same version of OrientDB as those used by Rexster. For example Rexster 2.5.0 uses OrientDB 1.7.6. You can find more details about Rexster installation at the Getting Started page. Configuration Refer to Rexster's Configuration page and OrientDB specific configuration page for the latest details. Synopsis The Rexster configuration file rexster.xml is used to configure parameters such as: TCP ports used by Rexster server modules to listen for incoming connections; character set supported by the Rexster REST requests and responses; connection parameters of graph instances. In order to configure Rexster to connect to your OrientDB graph, locate the rexster.xml in the Rexster directory and add the following snippet of code: ... ... true my-orient-graph orientgraph url-to-your-db user pwd ... 249 Rexster In the configuration file, there could be a sample graph element for an OrientDB instance ( ): orientdbsample you might edit it according to your needs. The element must be unique within the list of configured graphs and reports the name used to identify your graph. The element states whether the graph should be loaded and managed by Rexster. Setting its contents to prevent that graph from loading to Rexster; setting explicitly to type of graph by using an identifier ( orientgraph true the graph will be loaded. The false will element reports the for an OrientDB Graph instance) or the full name of the class that implements the GraphConfiguration interface (com.tinkerpop.rexster.OrientGraphConfiguration for an OrientDB Graph). The element reports the URL to the OrientDB database Rexster is expected to connect to: plocal:*path-to-db* remote:*url-to-db* (e.g. , if the graph can be accessed over the file system (e.g. ) , if the graph can be accessed over the network and/or if you want to enable multiple accesses to the graph remote:localhost/mydb memory:*db-name* plocal:/tmp/graph/db ) , if the graph resides in memory only. Updates to this kind of graph are never persistent and when the OrientDB server ends the graph is lost The and elements reports the credentials to access the graph (e.g. admin admin ). Run Note: only Rexster 0.5-S NAPS HOT and further releases work with OrientDB GraphEd In this section we present a step-by-step guide to Rexster-ify an OrientDB graph. We assume that: you created a Blueprints enabled graph called orientGraph using the class com.tinkerpop.blueprints.pgm.impls.orientdb.OrientGraph you inserted in the Rexster configuration file a graph-file element set to element with the remote:orienthost/orientGraph element set to my-orient-graph and the (if you do not remember how to do this, go back to the Configuration section). Be sure that the OrientDB server is running and you have properly configured the location and the access credentials of your graph. Execute the startup script ($REXSTER_HOME/bin/rexster.bat or $REXSTER_HOME/bin/rexster.sh) The shell console appears and you should see the following log message (line 10 states that the OrientDB graph instance has been loaded): [INFO] WebServer - .:Welcome to Rexster:. [INFO] GraphConfigurationContainer - Graph emptygraph - tinkergraph[vertices:0 edges:0] loaded [INFO] RexsterApplicationGraph - Graph [tinkergraph] - configured with allowable namespace [tp:gremlin] [INFO] GraphConfigurationContainer - Graph tinkergraph - tinkergraph[vertices:6 edges:6] loaded [INFO] RexsterApplicationGraph - Graph [tinkergraph-readonly] - configured with allowable namespace [tp:gremlin] [INFO] GraphConfigurationContainer - Graph tinkergraph-readonly - (readonly)tinkergraph[vertices:6 edges:6] loaded [INFO] RexsterApplicationGraph - Graph [gratefulgraph] - configured with allowable namespace [tp:gremlin] [INFO] GraphConfigurationContainer - Graph gratefulgraph - tinkergraph[vertices:809 edges:8049] loaded [INFO] GraphConfigurationContainer - Graph sailgraph - sailgraph[memorystore] loaded [INFO] GraphConfigurationContainer - Graph my-orient-graph - orientgraph[remote:orienthost/orientGraph] loaded [INFO] GraphConfigurationContainer - Graph neo4jsample [INFO] GraphConfigurationContainer - Graph dexsample - not enabled and not loaded. not enabled and not loaded. [INFO] MapResultObjectCache - Cache constructed with a maximum size of 1000 [INFO] WebServer - Web Server configured with com..sun..jersey..config..property..packages: com.tinkerpop.rexster [INFO] WebServer - No servlet initialization parameters passed for configuration: admin-server-configuration [INFO] WebServer - Rexster Server running on: [http://localhost:8182] [INFO] WebServer - Dog House Server running on: [http://localhost:8183] [INFO] ShutdownManager$ShutdownSocketListener - Bound shutdown socket to /127.0.0.1:8184. Starting listener thread for sh utdown requests. Now you can use Rexster REST API and The Dog House web application to retrieve and modify the data stored in the OrientDB graph. 250 Gephi Graph Render Gephi Visual Tool Introduction Gephi is a visual tool to manipulate and analyze graphs. Gephi is an Open Source project. Take a look at the amazing features. Gephi can be used to analyze graphs extracted from OrientDB. There are 2 level of integration: the Streaming plugin that calls OrientDB server via HTTP. OrientDB exposes the new "/gephi" command in HTTP GET method that executes a query and returns the result set in "gephi" format. Gephi importer for Blueprints In this mini guide we will take a look at the first one: the streaming plugin. For more information: Gephi Graph Streaming format Graph Streaming plugin Tutorial video Getting started Before to start assure you've OrientDB 1.1.0-SNAPSHOT or greater. Download and install 1. To download Gephi goto: http://gephi.org/users/download/ 2. Install it, depends on your OS 3. Run Gephi 4. Click on the menu Tools -> Plugins 251 Gephi Graph Render 5. Click on the tab Available Plugins 6. Select the plugin Graph S treaming, click on the Install button and wait the plugin is installed Import a graph in Gephi Before to import a graph assure a OrientDB server instance is running somewhere. For more information watch this video. 1. Go to the Overview view (click on Overview top left button) 2. Click on the S treaming tab on the left 3. Click on the big + green button 4. Insert as S ource URL the query you want to execute. Example: http://localhost:2480/gephi/demo/sql/select%20from%20v/100 (below more information about the syntax of query) 5. Select as S tream type the JS ON format (OrientDB talks in JSON) 6. Enable the Use Basic Authentication and insert the user and password of OrientDB database you want to access. The default user is "admin" as user and password 7. Click on OK button Executing a query The OrientDB's "/gephi" HTTP command allow to execute any query. The format is: http://:/gephi///[/] Where: host is the host name or the ip address where the OrientDB server is running. If you're executing OrientDB on the same machine where Gephi is running use "localhost" port is the port number where the OrientDB server is running. By default is 2480. database is the database name language query , the query text following the URL encoding rules. For example to use the spaces use becomes limit %20 , so the query select from v select%20from%20v , optional, set the limit of the result set. If not defined 20 is taken by default. -1 means no limits SQL Graph language To use the OrientDB's SQL language use sql as language. For more information look at the SQL-Syntax. For example, to return the first 1,000 vertices (class V) with outgoing connections the query would be: SELECT FROM V WHERE out.size() > 0 Executed on "localhost" against the "demo" database + encoding becomes: http://localhost:2480/gephi/demo/sql/select%20from%20V%20where%20out.size()%20%3E%200/1000 GREMLIN language To use the powerful GREM LIN language to retrieve the graph or a portion of it use gremlin as language. For more information look at the GREM LIN syntax. For example, to return the first 100 vertices: g.V[0..99] 252 Gephi Graph Render Executed on "localhost" against the "demo" database + encoding becomes: http://localhost:2480/gephi/demo/gremlin/g.V%5B0..99%5D/-1 For more information about using Gephi look at Learn how to use Gephi 253 spider-box spider-box spider-box is not really a "plug-in", but more a quick way to set up an environment to play with OrientDB in a local VM . It requires a virtualization system like Virtualbox, VM Ware Fusion or Parallels and the provisioning software Vagrant. Once installed, you can very quickly start playing with the newest version of OrientDB Studio or the console. Or even start developing software with OrientDB as the database. spider-box is configured mainly to build a PHP development environment. But, since it is built on Puphpet, you can easily change the configuration, so Python or even node.js is also installed. Ruby is installed automatically. If you have questions about changing configuration or using spider-box, please do ask in an issue in the spider-box repo. Have fun playing with OrientDB and spider-box! Note: Neo4j and Gremlin Server are also installed, when you vagrant up spider-box. 254 3rd Party Plugins Plugins If you're looking for drivers or JDBC connector go to Programming-Language-Bindings. OrientDB Spring Data is the official Spring Data Plugin for both Graph and Document APIs spring-orientdb is an attempt to provide a PlatformTransactionM anager for OrientDB usable with the Spring Framework, in particular with @Transactional annotation. Apache 2 license Spring Session OrientDB is a Spring Session extension for OrientDB. Play Framework 2.1 PLAY-WITH-ORIENTDB plugin Play Framework 2.1 ORIGAM I plugin Play Framework 1.x ORIENTDB plugin Frames-OrientDB Plugin Play Framework 2.x Frames-OrientDB plugin is a Java O/G mapper for the OrientDB with the Play! framework 2. It is used with the TinkerPop Frames for O/G mapping. 255 3rd Party Plugins With proper mark-up/logic separation, a POJO data model, and a refreshing lack of XM L, Apache Wicket makes developing web-apps simple and enjoyable again. Swap the boilerplate, complex debugging and brittle code for powerful, reusable components written with plain Java and HTM L. Guice (pronounced 'juice') is a lightweight dependency injection framework for Java 6 and above, brought to you by Google. OrientDB Guice plugin allows to integrate OrientDB inside Guice. Features: Integration through guice-persist (UnitOfWork, PersistService, @Transactional, dynamic finders supported) Support for document, object and graph databases Database types support according to classpath (object and graph db support activated by adding jars to classpath) Auto mapping entities in package to db scheme or using classpath scanning to map annotated entities Auto db creation Hooks for schema migration and data initialization extensions All three database types may be used in single unit of work (but each type will use its own transaction) Vert.x is a lightweight, high performance application platform for the JVM that's designed for modern mobile, web, and enterprise applications. Vert.x Persistor M odule for Tinkerpop-compatible Graph Databases like OrientDB. Gephi Visual tool usage with OrientDB and the Blueprints importer OrientDB session store for Connect Puppet module Chef 256 3rd Party Plugins Apache Tomcat realm plugin by Jonathan Tellier Shibboleth connector by Jonathan Tellier. The Shibboleth System is a standards based, open source software package for web single sign-on across or within organizational boundaries. It allows sites to make informed authorization decisions for individual access of protected online resources in a privacy-preserving manner Griffon plugin, Apache 2 license JCA connectors OPS4J Orient provides a JCA resource adapter for integrating OrientDB with Java EE 6 servers OrientDB JCA connector to access to OrientDB database via JCA API + XA Transactions Pacer plugin by Paul Dlug. Pacer is a JRuby graph traversal framework built on the Tinkerpop stack. This plugin enables full OrientDB graph support in Pacer. EventStore for Axonframework, which uses fully transactional (full ACID support) NoSQL database OrientDB. Axon Framework helps build scalable, extensible and maintainable applications by supporting developers apply the Command Query Responsibility Segregation (CQRS) architectural pattern Accessing OrientDB using Slick 257 3rd Party Plugins Jackrabbit module to use OrientDB as backend. orientqb orientqb is a builder for OSQL query language written in Java. orientqb has been thought to help developers in writing complex queries dynamically and aims to be simple but powerful. 258 Data M odeling Multi-Model The OrientDB engine supports Graph, Document, Key/Value, and Object models, so you can use OrientDB as a replacement for a product in any of these categories. However, the main reason why users choose OrientDB is because of its true Multi-Model DBM S abilities, which combine all the features of the four models into the core. These abilities are not just interfaces to the database engine, but rather the engine itself was built to support all four models. This is also the main difference to other multi-model DBM Ss, as they implement an additional layer with an API, which mimics additional models. However, under the hood, they're truly only one model, therefore they are limited in speed and scalability. The Document Model The data in this model is stored inside documents. A document is a set of key/value pairs (also referred to as fields or properties), where the key allows access to its value. Values can hold primitive data types, embedded documents, or arrays of other values. Documents are not typically forced to have a schema, which can be advantageous, because they remain flexible and easy to modify. Documents are stored in collections, enabling developers to group data as they decide. OrientDB uses the concepts of "classes" and "clusters" as its form of "collections" for grouping documents. This provides several benefits, which we will discuss in further sections of the documentation. OrientDB's Document model also adds the concept of a "LINK" as a relationship between documents. With OrientDB, you can decide whether to embed documents or link to them directly. When you fetch a document, all the links are automatically resolved by OrientDB. This is a major difference to other Document Databases, like M ongoDB or CouchDB, where the developer must handle any and all relationships between the documents herself. The table below illustrates the comparison between the relational model, the document model, and the OrientDB document model: Relational Model Document Model OrientDB Document Model Table Collection Class or Cluster Row Document Document Column Key/value pair Document field Relationship not available Link The Graph Model A graph represents a network-like structure consisting of Vertices (also known as Nodes) interconnected by Edges (also known as Arcs). OrientDB's graph model is represented by the concept of a property graph, which defines the following: Vertex - an entity that can be linked with other Vertices and has the following mandatory properties: unique identifier set of incoming Edges set of outgoing Edges Edge - an entity that links two Vertices and has the following mandatory properties: unique identifier link to an incoming Vertex (also known as head) link to an outgoing Vertex (also known as tail) label that defines the type of connection/relationship between head and tail vertex In addition to mandatory properties, each vertex or edge can also hold a set of custom properties. These properties can be defined by users, which can make vertices and edges appear similar to documents. In the table below, you can find a comparison between the graph model, the relational data model, and the OrientDB graph model: 259 Data M odeling Relational Model Graph Model OrientDB Graph Model Table Vertex and Edge Class Class that extends "V" (for Vertex) and "E" (for Edges) Row Vertex Vertex Column Vertex and Edge property Vertex and Edge property Relationship Edge Edge The Key/Value Model This is the simplest model of the three. Everything in the database can be reached by a key, where the values can be simple and complex types. OrientDB supports Documents and Graph Elements as values allowing for a richer model, than what you would normally find in the classic Key/Value model. The classic Key/Value model provides "buckets" to group key/value pairs in different containers. The most classic use cases of the Key/Value M odel are: POST the value as payload of the HTTP call -> // GET the value as payload from the HTTP call -> // DELETE the value by Key, by calling the HTTP call -> // The table below illustrates the comparison between the relational model, the Key/Value model, and the OrientDB Key/Value model: Relational Model Key/Value Model OrientDB Key/Value Model Table Bucket Class or Cluster Row Key/Value pair Document Column not available Document field or Vertex/Edge property Relationship not available Link The Object Model This model has been inherited by Object Oriented programming and supports Inheritance between types (sub-types extends the super-types), Polymorphism when you refer to a base class and Direct binding from/to Objects used in programming languages. The table below illustrates the comparison between the relational model, the Object model, and the OrientDB Object model: Relational Model Object Model OrientDB Object Model Table Class Class or Cluster Row Object Document or Vertex Column Object property Document field or Vertex/Edge property Relationship Pointer Link 260 M ulti Tenant Multi Tenant There are at many ways to build multi-tenant applications on top of OrientDB, in this page we are going to analyze pros and cons of three of the most used approaches. One database per tenant With this solution, each tenant is a database. The OrientDB server allows to host multiple databases. Pros: Easy to use: to create/drop a new tenant, simply create/drop the database Easy to scale up by moving the database on different servers Cons: Hard to create reports and analytics cross tenant, it requires to execute the same query against all the databases Specific clusters per tenant With this solution, each tenant is stored in one or more clusters of the same database. For example, the class following clusters: Product_ClientA , Product_ClientB , Product_ClientC Product could have the . In this way a query against a specific cluster will be used to retrieve data from one tenant only. Example to retrieve all the products of 2016, ordered by the most recent, only for the tenant "ClientC": select * from cluster:Product_ClientC where date >= '2016-01-01' order by date desc Instead, a query against the class 01' order by date desc Product will return a cross-tenant result. Example: . select * from Product where date >= '2016-01- . Pros: Easy to create reports and analytics cross tenant, because it's just one database It's possible to scale up on multiple servers by using sharding Cons: The maximum number of clusters per database is 32,768. To bypass this limitation, use multiple databases No security out of the box, it's entirely up to the application to isolate access between tenants Use Partitioned Graphs By using the OrientDB's record level security, it's possible to have multiple partitions of graphs accessible by different users. For more information look at Partitioned Graphs. Pros: Easy to create reports and analytics cross tenant, because it's just one database Cons: Performance: record level security has an overhead, specially with queries Scales worse than "One database per tenant" solution, because the database will end up to be much bigger Sharding is not possible because records of multiple tenants are mixed on the same clusters Hard to guarantee a predictable level of service for all the users, because users connect to a tenant impact the other tenants 261 Basic Concepts Basic Concepts Record The smallest unit that you can load from and store in the database. Records come in four types: Documents Blobs Vertices Edges A Record is the smallest unit that can be loaded from and stored into the database. A record can be a Document, a Blob a Vertex or even an Edge. Document The Document is the most flexible record type available in OrientDB. Documents are softly typed and are defined by schema classes with defined constraints, but you can also use them in a schema-less mode too. Documents handle fields in a flexible manner. You can easily import and export them in JSON format. For example, { "name" : "Jay", "surname" : "Miner", "job" : "Developer", "creations" : [ { "name" : "Amiga 1000", "company" : "Commodore Inc." }, { "name" : "Amiga 500", "company" : "Commodore Inc." } ] } For Documents, OrientDB also supports complex relationships. From the perspective of developers, this can be understood as a persistent Map . BLOB In addition to the Document record type, OrientDB can also load and store binary data. The BLOB record type was called RecordBytes before OrientDB v2.2. Vertex In Graph databases, the most basic unit of data is the node, which in OrientDB is called a vertex. The Vertex stores information for the database. There is a separate record type called the Edge that connects one vertex to another. Vertices are also documents. This means they can contain embedded records and arbitrary properties. Edge In Graph databases, an arc is the connection between two nodes, which in OrientDB is called an edge. Edges are bidirectional and can only connect two vertices. Edges can be regular or lightweight. The Regular Edge saves as a Document, while the Lightweight Edge does not. For an understanding of the differences between these, see Lightweight Edges. For more information on connecting vertices in general, see Relationships, below. 262 Basic Concepts Record ID When OrientDB generates a record, it auto-assigns a unique unit identifier, called a Record ID, or RID. The syntax for the Record ID is the pound sign with the cluster identifier and the position. The format is like this: #: . Cluster Identifier: This number indicates the cluster to which the record belongs. Positive numbers in the cluster identifier indicate persistent records. Negative numbers indicate temporary records, such as those that appear in result-sets for queries that use projections. Position: This number defines the absolute position of the record in the cluster. NOTE: The prefix character # is mandatory to recognize a Record ID. Records never lose their identifiers unless they are deleted. When deleted, OrientDB never recycles identifiers. Additionally, you can access records directly through their Record ID's. For this reason, you don't need to create a field to serve as the primary key, as you do in Relational databases. Record Version Records maintain their own version number, which increments on each update. In optimistic transactions, OrientDB checks the version in order to avoid conflicts at commit time. Class The concept of the Class is taken from the Object Oriented Programming paradigm. In OrientDB, classes define records. It is closest to the concept of a table in Relational databases. Classes can be schema-less, schema-full or a mix. They can inherit from other classes, creating a tree of classes. Inheritance, in this context, means that a sub-class extends a parent class, inheriting all of its attributes. Each class has its own clusters (data files). A non-abstract class (see below) must have at least one cluster defined, which functions as its default cluster. But, a class can support multiple clusters. When you execute a query against a class, it automatically propagates to all clusters that are part of the class. When you create a new record, OrientDB selects the cluster to store it in using a configurable strategy. When you create a new class, by default, OrientDB creates new persistent clusters with the same name as the class, in lowercase, suffixed with underscore and an integer. As a default, OrientDB creates as many clusters per class as many cores (processors) the host machine has. Eg. for class Person , OrientDB will create clusters person , person_1 , person_2 and so on so forth. Abstract Class The concept of an Abstract Class is one familiar to Object-Oriented programming. In OrientDB, this feature has been available since version 1.2.0. Abstract classes are classes used as the foundation for defining other classes. They are also classes that cannot have instances. For more information on how to create an abstract class, see CREATE CLASS. This concept is essential to Object Orientation, without the typical spamming of the database with always empty, auto-created clusters. For more information on Abstract Class as a concept, see Abstract Type and Abstract M ethods and Classes Class vs. Cluster in Queries The combination of classes and clusters is very powerful and has a number of use cases. Consider an example where you create a class Invoice , with two clusters orientdb> invoice2015 and invoice2016 . You can query all invoices using the class as a target with SELECT . SELECT FROM Invoice 263 Basic Concepts In addition to this, you can filter the result-set by year. The class Invoice includes a year field, you can filter it through the WHERE clause. orientdb> SELECT FROM Invoice WHERE year = 2012 You can also query specific objects from a single cluster. By splitting the class Invoice across multiple clusters, (that is, one per year), you can optimize the query by narrowing the potential result-set. orientdb> SELECT FROM CLUSTER:invoice2012 Due to the optimization, this query runs significantly faster, because OrientDB can narrow the search to the targeted cluster. Cluster Where classes provide you with a logical framework for organizing data, clusters provide physical or in-memory space in which OrientDB actually stores the data. It is comparable to the collection in Document databases and the table in Relational databases. When you create a new class, the process also creates physical clusters that serve as the default location in which to CREATE CLASS store data for that class. OrientDB forms the cluster names using the class name, with all lower case letters. Beginning with version 2.2, OrientDB creates additional clusters for each class, (one for each CPU core on the server), to improve performance of parallelism. For more information, see the Clusters Tutorial. Relationships OrientDB supports two kinds of relationships: referenced and embedded. It can manage relationships in a schema-full or schema-less scenario. Referenced Relationships In Relational databases, tables are linked through relationships natively without computing JOIN JOIN commands, which can prove costly on computing resources. OrientDB manges 's. Instead, it stores direct links to the target objects of the relationship. This boosts the load speed for the entire graph of connected objects, such as in Graph and Object database systems. For example customer Record A -------------> Record B CLASS=Invoice CLASS=Customer RID=5:23 RID=10:2 Here, record A contains the reference to record B in the property customer . Note that both records are reachable by other records, given that they have a Record ID. With the Graph API, Edges are represented with two links stored on both vertices to handle the bidirectional relationship. 1:1 and 1:n Referenced Relationships OrientDB expresses relationships of these kinds using links of the LINK type. 1:n and n:n Referenced Relationships OrientDB expresses relationships of these kinds using a collection of links, such as: LINKLIST An ordered list of links. LINKSET An unordered set of links, which does not accept duplicates. LINKMAP An ordered map of links, with String as the key type. Duplicates keys are not accepted. 264 Basic Concepts With the Graph API, Edges connect only two vertices. This means that 1:n relationships are not allowed. To specify a 1:n relationship with graphs, create multiple edges. Embedded Relationships When using Embedded relationships, OrientDB stores the relationship within the record that embeds it. These relationships are stronger than Reference relationships. You can represent it as a UM L Composition relationship. Embedded records do not have their own Record ID, given that you can't directly reference it through other records. It is only accessible through the container record. In the event that you delete the container record, the embedded record is also deleted. For example, 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 reach record B only by traversing the container record. For example, orientdb> SELECT FROM Account WHERE address.city = 'Rome' 1:1 and n:1 Embedded Relationships OrientDB expresses relationships of these kinds using the EMBEDDED type. 1:n and n:n Embedded Relationships OrientDB expresses relationships of these kinds using a collection of links, such as: EMBEDDEDLIST An ordered list of records. EMBEDDEDSET An unordered set of records, that doesn't accept duplicates. EMBEDDEDMAP An ordered map of records as the value and a string as the key, it doesn't accept duplicate keys. Inverse Relationships In OrientDB, all Edges in the Graph model are bidirectional. This differs from the Document model, where relationships are always unidirectional, requiring the developer to maintain data integrity. In addition, OrientDB automatically maintains the consistency of all bidirectional relationships. Database The database is an interface to access the real Storage. IT understands high-level concepts such as queries, schemas, metadata, indices and so on. OrientDB also provides multiple database types. For more information on these types, see Database Types. Each server or Java VM can handle multiple database instances, but the database name must be unique. You can't manage two databases at the same time, even if they are in different directories. To handle this case, use the / $ dollar character as a separator instead of the slash character. OrientDB binds the entire name, so it becomes unique, but at the file system level it converts $ with / , allowing multiple databases with the same name in different paths. For example, test$customers -> test/customers production$customers = production/customers Database URL OrientDB uses its own URL format, of engine and database name as : . 265 Basic Concepts Engine Description Example plocal This engine writes to the file system to store data. There is a LOG of changes to restore the storage in case of a crash. plocal:/temp/databases/petshop/petshop memory Open a database completely in memory memory:petshop remote The storage will be opened via a remote network connection. It requires an OrientDB Server up and running. In this mode, the database is shared among multiple clients. Syntax: remote:: []/db-name . The port is optional and defaults to 2424. remote:localhost/petshop Database Usage You must always close the database once you finish working on it. NOTE: OrientDB automatically closes all opened databases, when the process dies gracefully (not by killing it by force). This is assured if the Operating System allows a graceful shutdown. 266 OrientDB Programs OrientDB Programs 267 OrientDB Server-Startup Programs OrientDB Server Startup Programs 268 server 269 dserver 270 orientdb 271 OrientDB Client Programs OrientDB Client Programs 272 Console Console OrientDB provides a Console Tool, which is a Java application that connects to and operates on OrientDB databases and Server instances. 273 Console Console Modes There are two modes available to you, while executing commands through the OrientDB Console: interactive mode and batch mode. Interactive Mode By default, the Console starts in interactive mode. In this mode, the Console loads to an orientdb> prompt. From there you can execute commands and SQL statements as you might expect in any other database console. You can launch the console in interactive mode by executing the systems in the bin console.sh for Linux OS systems or console.bat for Windows directory of your OrientDB installation. Note that running this file requires execution permissions. $ cd $ORIENTDB_HOME/bin $ ./console.sh OrientDB console v.X.X.X (build 0) www.orientdb.com Type 'HELP' to display all the commands supported. Installing extensions for GREMLIN language v.X.X.X orientdb> From here, you can begin running SQL statements or commands. For a list of these commands, see commands. Batch mode When the Console runs in batch mode, it takes commands as arguments on the command-line or as a text file and executes the commands in that file in order. Use the same console.sh or console.bat file found in bin at the OrientDB installation directory. Command-line: To execute commands in batch mode from the command line, pass the commands you want to run in a string, separated by a semicolon. $ $ORIENTDB_HOME/bin/console.sh "CONNECT REMOTE:localhost/demo;SELECT FROM Profile" S cript Commands: In addition to entering the commands as a string on the command-line, you can also save the commands to a text file as a semicolon-separated list. $ vim commands.txt CONNECT REMOTE:localhost/demo;SELECT FROM Profile $ $ORIENTDB_HOME/bin/console.sh commands.txt Ignoring Errors When running commands in batch mode, you can tell the console to ignore errors, allowing the script to continue the execution, with the ignoreErrors $ setting. vim commands.txt SET ignoreErrors TRUE Enabling Echo 274 Console Regardless of whether you call the commands as an argument or through a file, when you run console commands in batch mode, you may also need to display them as they execute. You can enable this feature using the echo setting, near the start of your commands list. $ vim commands.txt SET echo TRUE Enabling Date in prompt Starting from v2.2.9, to enable the date in the prompt, set the variable promptDateFormat with the date format following the SimpleDateFormat specs. orientdb {db=test1}> set promptDateFormat "yyy-MM-dd hh:mm:ss.sss" orientdb {db=test1 (2016-08-26 09:34:12.012)}> 275 Console Console Commands OrientDB implements a number of SQL statements and commands that are available through the Console. In the event that you need information while working in the console, you can access it using either the Command HELP or ? command. Description BACKUP DATABASE Backup a database BROWSE CLASS Browses all the records of a class BROWSE CLUSTER Browses all the records of a cluster CLASSES Displays all the configured classes CLUSTER STATUS Displays the status of distributed cluster of servers CLUSTERS Displays all the configured clusters CONFIG Displays the configuration where the opened database is located (local or remote) CONFIG GET Returns a configuration value CONFIG SET Set a configuration value CONNECT Connects to a database CREATE DATABASE Creates a new database DECLARE INTENT Declares an intent DICTIONARY KEYS Displays all the keys in the database dictionary DICTIONARY GET Loookups for a record using the dictionary. If found set it as the current record DICTIONARY PUT Inserts or modify an entry in the database dictionary. The entry is composed by key=String, value=recordid DICTIONARY REMOVE Removes the association in the dictionary DISCONNECT Disconnects from the current database DISPLAY RECORD Displays current record's attributes DISPLAY RAW RECORD Displays current record's raw format DROP DATABASE Drop a database EXPORT DATABASE Exports a database EXPORT RECORD Exports a record in any of the supported format (i.e. json) FREEZE DATABASE Freezes the database locking all the changes. Use this to raw backup. Once frozen it uses the DATABASE to release it GET Returns the value of a property IMPORT DATABASE Imports a database previously exported INDEXES Displays information about indexes INFO Displays information about current status INFO CLASS Displays information about a class JS Executes a Javascript in the console JSS Executes a Javascript in the server LIST DATABASES List the available databases LIST CONNECTIONS RELEASE List the available connections 276 Console LOAD RECORD Loads a record in memory and set it as the current one LOAD SCRIPT Loads and executes a sql script PROFILER Controls the Profiler PROPERTIES Returns all the configured properties pwd Display current path RELEASE DATABASE Releases a Console Freeze Database database RELOAD RECORD Reloads a record in memory and set it as the current one RELOAD SCHEMA Reloads the schema RESTORE DATABASE Restore a database SET Changes the value of a property HELP Prints this help EXIT Closes the console SQL Commands 277 Console Console - BACKUP Executes a complete backup on the currently opened database. It then compresses the backup file using the ZIP algorithm. You can then restore a database from backups, using the RESTORE DATABASE command. You can automate backups using the Automatic-Backup server plugin. Backups and restores are similar to the EXPORT DATABASE and IMPORT DATABASE , but they offer better performance than these options. NOTE: OrientDB Community Edition does not support backing up remote databases. OrientDB Enterprise Edition does support this feature. For more information on how to implement this with Enterprise Edition, see Remote Backups. S yntax: BACKUP DATABASE [-incremental] [-compressionLevel=] [-bufferSize=] -incremental Defines the path to the backup file. Option to execute an incremental backup. When enabled, it computes the data to backup as all new changes since the last backup. Available only in the OrientDB Enterprise Edition version 2.2 or later. - compressionLevel Defines the level of compression for the backup file. Valid levels are 0 to 9 . The default is 9 . Available in 1.7 or later. -bufferSize Defines the compression buffer size. By default, this is set to 1M B. Available in 1.7 or later. Permissions: In order to enable a user to execute this command, you must add the permission of create for the resource database.backup to the database user. Example: Backing up a database: orientdb> CONNECT plocal:../databases/mydatabase admin admin orientdb> BACKUP DATABASE /backups/mydb.zip Backing current database to: database mydb.zip Backup executed in 0.52 seconds Incremental Backup Since version 2.2, OrientDB Enterprise Edition supports incremental backups. For more details see Incremental Backup and Restore For more information, see: Restore Database Export Database Import Database Console-Commands ODatabaseExport Java class 278 Console Console - BROWSE CLASS Displays all records associated with the given class. S yntax: BROWSE CLASS Defines the class for the records you want to display. Permissions: In order to enable a user to execute this command, you must add the permission of read for the resource database.class. to the database user. Example: Browse records associated with the class orientdb> City : BROWSE CLASS City ----+------+------------------# | RID | NAME ----+------+------------------0 | -6:0 | Rome 1 | -6:1 | London 2 | -6:2 | Honolulu ----+------+------------------- For more information on other commands, see Console Commands. 279 Console Console - BROWSE CLUSTER Displays all records associated with the given cluster. S yntax: BROWSE CLUSTER Defines the cluster for the records you want to display. Permissions: In order to enable a user to execute this command, you must add the permission of read for the resource database.cluster. to the database user. Example: Browse records associated with the cluster orientdb> City : BROWSE CLUSTER City ----+------+------------------# | RID | NAME ----+------+------------------0 | -6:0 | Rome 1 | -6:1 | London 2 | -6:2 | Honolulu ----+------+------------------- For more information on other commands, see Console Commands. 280 Console Console - LIST CLASSES Displays all configured classes in the current database. S yntax: Long Syntax: LIST CLASSES Short Syntax: CLASSES Example List current classes in the database: orientdb> LIST CLASSES CLASSES -------------+------+-------------+----------NAME | ID | CLUSTERS | ELEMENTS -------------+------+-------------+----------Person | 0 | person | 7 Animal | 1 | animal | 5 AnimalRace | 2 | AnimalRace | 0 AnimalType | 3 | AnimalType | 1 OrderItem | 4 | OrderItem | 0 Order | 5 | Order | 0 City | 6 | City | 3 -------------+------+-------------+----------TOTAL 16 ----------------------------------------------- For more information on other commands, see Console Commands. 281 Console Console - CLUSTER STATUS Displays the status of the cluster in distributed configuration. S yntax: CLUSTER STATUS Example: Display the status of the cluster: orientdb> CLUSTER STATUS { "localName": "_hzInstance_1_orientdb", "localId": "3735e690-9a7b-44d2-b4bc-27089da065e2", "members": [ { "id": "3735e690-9a7b-44d2-b4bc-27089da065e2", "name": "node1", "startedOn": "2015-05-14 17:06:40:418", "listeners": [ { "protocol": "ONetworkProtocolBinary", "listen": "10.3.15.55:2424" }, { "protocol": "ONetworkProtocolHttpDb", "listen": "10.3.15.55:2480" } ], "databases": [] } ] } For more information on other commands, see Console Commands. 282 Console Console - LIST CLUSTERS Displays all configured clusters in the current database. S yntax: Long Syntax: LIST CLUSTERS Short Syntax: CLUSTERS Example: List current clusters on database: orientdb> LIST CLUSTERS CLUSTERS -------------+------+-----------+----------NAME | ID | TYPE | ELEMENTS -------------+------+-----------+----------metadata | 0 | Physical | 11 index | 1 | Physical | 0 default | 2 | Physical | 779 csv | 3 | Physical | 1000 binary | 4 | Physical | 1001 person | 5 | Physical | 7 animal | 6 | Physical | 5 animalrace | -2 | Logical | 0 animaltype | -3 | Logical | 1 orderitem | -4 | Logical | 0 order | -5 | Logical | 0 city | -6 | Logical | 3 -------------+------+-----------+----------TOTAL 2807 -------------------------------------------- For information on creating new clusters in the current database, see the CREATE CLUSTER command. For more information on other commands, see Console Commands. 283 Console Console - LIST SERVERS Displays all active servers connected within a cluster. This command was introduced in OrientDB version 2.2. S yntax: LIST SERVERS Example: List the servers currently connected to the cluster: orientdb> LIST SERVERS CONFIGURED SERVERS -+----+------+-----------+-------------+-----------+-----------+-----------+---------+--------#|Name|Status|Connections|StartedOn |Binary |HTTP |UsedMemory |FreeMemory|MaxMemory -+----+------+-----------+-------------+-----------+-----------+-----------+---------+--------0|no2 |ONLINE|0 |2015-10- 30...|192.168.0.6|192.168.0.6|80MB(8.80%)|215MB(23%)|910MB 1|no1 |ONLINE|0 |2015-10-30...|192.168.0.6|192.168.0.6|90MB(2.49%)|195MB(5%) |3.5GB -+----+------+-----------+-------------+-----------+-----------+-----------+---------+--------- Use the DISPLAY orientdb> command to show information on a specific server: DISPLAY 0 -------------+-----------------------------Name | Value -------------+-----------------------------Name | node2 Status | ONLINE Connections | 0 StartedOn | Fri Oct 30 21:41:07 CDT 2015 Binary | 192.168.0.6:2425 HTTP | 192.168.0.6:2481 UsedMemory | 80,16MB (8,80%) FreeMemory | 215,34MB (23,65%) MaxMemory | 910,50MB -------------+------------------------------ For more information on other commands, see Console Commands. 284 Console Console - LIST SERVER USERS This feature was introduced in OrientDB version 2.2. Displays all configured users on the server. In order to display the users, the current system user that is running the console must have permissions to read the $ORIENTDB_HOME/config/orientdb-server-config.xml configuration file. For more information, see OrientDB Server Security. S yntax: LIST SERVER USERS Example: List configured users on a server: orientdb> LIST SERVER USERS SERVER USERS - 'root', permissions: * - 'guest', permissions: connect,server.listDatabases,server.dblist For more information, see SET SERVER USER DROP SERVER USER For more information on other console commands, see Console Commands. 285 Console Console - CHECK DATABASE Checks the integrity of a database. In the case the database contains graphs, their consistency is checked. To repair a database, use Repair Database Command. S yntax CHECK DATABASE [--skip-graph] [-v] [--skip-graph] [-v] Skips the check of the graph Verbose mode Examples Check a graph database: orientdb> CHECK DATABASE Check of graph 'plocal:/temp/testdb' is started ... Scanning 1 edges (skipEdges=0)... + found corrupted edge E#17:0{out:#9:0,in:#11:0,test:true} v2 because incoming vertex (#11:0) does not contain the edge Scanning edges completed Scanning 710 vertices... + found corrupted vertex V#10:0{in_:[#17:0],name:Marko} v2 the edge should be removed from property in_ (ridbag) Scanning vertices completed Check of graph 'plocal:/temp/testdb' completed in 0 secs scannedEdges.....: 1 edgesToRemove....: 1 scannedVertices..: 710 scannedLinks.....: 2 linksToRemove....: 1 verticesToRepair.: 0 Check of storage completed in 296ms. without errors. For more information on other commands, see Console Commands. 286 Console Console - CONFIG Displays the configuration information on the current database, as well as whether it is local or remote. S yntax CONFIG Examples Display the configuration of the current database: orientdb> CONFIG REMOTE SERVER CONFIGURATION: +------------------------------------+--------------------------------+ | NAME | VALUE | +------------------------------------+--------------------------------+ | treemap.lazyUpdates | 300 | | db.cache.enabled | false | | file.mmap.forceRetry | 5 | | treemap.optimizeEntryPointsFactor | 1.0 | | storage.keepOpen | true | | treemap.loadFactor | 0.7 | | file.mmap.maxMemory | 110000000 | | network.http.maxLength | 10000 | | storage.cache.size | 5000 | | treemap.nodePageSize | 1024 | | ... | ... | | treemap.entryPoints | 30 | +------------------------------------+--------------------------------+ You can change configuration variables displayed here using the configuration variable, use the CONFIG GET CONFIG SET command. To display the value set to one command. For more information on other commands, see Console Commands. 287 Console Console - CONFIG GET Displays the value of the requested configuration variable. S yntax CONFIG GET Defines the configuration variable you want to query. Examples Display the value to the orientdb> tx.log.fileType configuration variable: CONFIG GET tx.log.fileType Remote configuration: tx.log.fileType = classic You can display all configuration variables using the CONFIG command. To change the values, use the CONFIG SET command. For more information on other commands, see Config Commands. 288 Console Console - CONFIG SET Updates a configuration variable to the given value. S yntax CONFIG SET Defines the configuration variable you want to change. Defines the value you want to set. Example Display the current value for orientdb> tx.autoRetry : CONFIG GET tx.autoRetry Remote configuration: tx.autoRetry = 1 Change the tx.autoRetry orientdb> value to 5 : CONFIG SET tx.autoRetry 5 Remote configuration value changed correctly. Display new value: orientdb> CONFIG GET tx.autoRetry Remote configuration: tx.autoRetry = 5 You can display all configuration variables with the using the CONFIG GET CONFIG command. You can view the current value on a configuration variable command. For more information on other commands, see Console Commands 289 Console Console - CONNECT Opens a database. S yntax CONNECT Defines the URL of the database you want to connect to. It uses the format Defines the mode you want to use in connecting to the database. It can be Defines the path to the database. : plocal or remote . Defines the user you want to connect to the database with. Defines the password needed to connect to the database, with the defined user. Examples: Connect to a local database as the user orientdb> admin , loading it directly into the console: connect plocal:../databases/GratefulDeadConcerts admin my_admin_password Connecting to database [plocal:../databases/GratefulDeadConcerts]...OK Connect to a remote database: orientdb> connect remote:192.168.1.1/GratefulDeadConcerts admin my_admin_password Connecting to database [remote:192.168.1.1/GratefulDeadConcerts]...OK For more information on other commands, see Console Commands. 290 Console Console - CREATE DATABASE Creates and connects to a new database. S yntax CREATE DATABASE [ []] [-restore=] Defines the URL of the database you want to connect to. It uses the format Defines the mode you want to use in connecting to the database. It can be Defines the path to the database. : or PLOCAL REMOTE . Defines the user you want to connect to the database with. Defines the password needed to connect to the database, with the defined user. Defines the storage type that you want to use. You can choose between Defines the database type. You can choose between GRAPH and DOCUMENT PLOCAL and . The default is MEMORY GRAPH . . Examples Create a local database orientdb> demo : CREATE DATABASE PLOCAL:/usr/local/orientdb/databases/demo Creating database [plocal:/usr/local/orientdb/databases/demo]... Connecting to database [plocal:/usr/local/orientdb/databases/demo]...OK Database created successfully. Current database is: plocal:/usr/local/orientdb/databases/demo orientdb {db=demo}> Create a remote database orientdb> trick : CREATE DATABASE REMOTE:192.168.1.1/trick root E30DD873203AAA245952278B4306D94E423CF91D569881B7CAD7D0B6D1A20CE9 PLOCAL Creating database [remote:192.168.1.1/trick ]... Connecting to database [remote:192.168.1.1/trick ]...OK Database created successfully. Current database is: remote:192.168.1.1/trick orientdb {db=trick}> To create a static database to use from the server, see To remove a database, see DROP DATABASE Server pre-configured storage types . . To change database configurations after creation, see ALTER DATABASE . For more information on other commands, see Console Commands. Incremental restore option You can execute an incremental restore at creation time through the option -restore specifying as value the path where your backup is placed. Let's suppose we want create a new fresh database "mydb" and restore data from a backup, located in /tmp/backup , performed from another database in one shot. In this case we can type: 291 Console orientdb> create database remote:localhost/mydb root root plocal graph -restore=/tmp/backup Creating database [remote:localhost/mydb] using the storage type [plocal]... Connecting to database [remote:localhost/mydb] with user 'admin'...OK Database created successfully. Current database is: remote:localhost/mydb For further details on incremental backup and restore you can refer to the page Incremental Backup and Restore. 292 Console Console - DECLARE INTENT Declares an intent for the current database. Intents allow you to tell the database what you want to do. S yntax DECLARE INTENT NULL Defines the name of the intent. OrientDB supports three intents: Removes the current intent. MASSIVEINSERT MASSIVEREAD Examples Declare an intent for a massive insert: orientdb> DECLARE INTENT MASSIVEINSERT After the insert, clear the intent: orientdb> DECLARE INTENT NULL For more information on other commands, see Console Commands. 293 Console Console - DICTIONARY GET Displays the value of the requested key, loaded from the database dictionary. S yntax DICTIONARY GET Defines the key you want to access. Example In a dictionary of U.S. presidents, display the entry for Barack Obama: orientdb> DICTIONARY GET obama ------------------------------------------------------------------------Class: Person id: 5:4 v.1 ------------------------------------------------------------------------parent: null children : [Person@5:5{parent:Person@5:4,children:null,name:Malia Ann, surname:Obama,city:null}, Person@5:6{parent:Person@5:4, children:null,name:Natasha,surname:Obama,city:null}] name : Barack surname : Obama city : City@-6:2{name:Honolulu} ------------------------------------------------------------------------- You can display all keys stored in a database using the DICTIONARY KEYS command. For more information on indexes, see Indexes. For more information on other commands, see Console Commands. 294 Console Console - DICTIONARY KEYS Displays all the keys stored in the database dictionary. S yntax DICTIONARY KEYS Example Display all the keys stored in the database dictionary: orientdb> DICTIONARY KEYS Found 4 keys: #0: key-148 #1: key-147 #2: key-146 #3: key-145 To load the records associated with these keys, use the DICTIONARY GET command. For more information on indexes, see Indexes. For more information on other commands, see Console Commands. 295 Console Console - DICTIONARY PUT Binds a record to a key in the dictionary database, making it accessible to the DICTIONARY GET command. S yntax DICTIONARY PUT Defines the key you want to bind. Defines the ID for the record you want to bind to the key. Example In the database dictionary of U.S. presidents, bind the record for Barack Obama to the key orientdb> obama : DICTIONARY PUT obama 5:4 -----------------------------------------------------------------------Class: Person id: 5:4 v.1 -----------------------------------------------------------------------parent : null children : [Person@5:5{parent:Person@5:4,children:null,name:Malia Ann, surname:Obama,city:null}, Person@5:6{parent:Person@5:4, children:null,name:Natasha,surname:Obama,city:null}] name : Barack surname : Obama city : City@-6:2{name:Honolulu} -----------------------------------------------------------------------The entry obama=5:4 has been inserted in the database dictionary To see all the keys stored in the database dictionary, use the DICTIONARY KEYS command. For more information on dictionaries and indexes, see Indexes. For more information on other commands, see Console Commands. 296 Console Console - DICTIONARY REMOVE Removes the association from the database dictionary. S yntax DICTIONARY REMOVE Defines the key that you want to remove. Example In a database dictionary of U.S. presidents, remove the key for Barack Obama: orientdb> DICTIONARY REMOVE obama Entry removed from the dictionary. Last value of entry was: -----------------------------------------------------------------------Class: Person id: 5:4 v.1 -----------------------------------------------------------------------parent : null children : [Person@5:5{parent:Person@5:4,children:null,name:Malia Ann, surname:Obama,city:null}, Person@5:6{parent:Person@5:4, children:null,name:Natasha,surname:Obama,city:null}] name : Barack surname : Obama city : City@-6:2{name:Honolulu} ------------------------------------------------------------------------ You can display information for all keys stored in the database dictionary using the DICTIONARY KEY command. For more information on dictionaries and indexes, see Indexes. For more information on other commands, see Console Commands. 297 Console Console - DISCONNECT Closes the currently opened database. S yntax DISCONNECT Example Disconnect from the current database: orientdb> DISCONNECT Disconnecting from the database [../databases/petshop/petshop]...OK To connect to a database, see CONNECT . For more information on other commands, see Console Commands. 298 Console Console - DISPLAYS RECORD Displays details on the given record from the last returned result-set. S yntax DISPLAY RECORD Defines the relative position of the record in the last result-set. Example Query the database on the class orientdb> Person to generate a result-set: SELECT FROM Person ---+-----+--------+----------+-----------+-----------+-----# | RID | PARENT | CHILDREN | NAME | SURNAME | City ---+-----+--------+----------+-----------+-----------+-----0 | 5:0 | null | null | Giuseppe | Garibaldi | -6:0 1 | 5:1 | 5:0 | null | Napoleon | Bonaparte | -6:0 2 | 5:2 | 5:3 | null | Nicholas | Churchill | -6:1 3 | 5:3 | 5:2 | null | Winston | Churchill | -6:1 4 | 5:4 | null | [2] | Barack | Obama | -6:2 5 | 5:5 | 5:4 | null | Malia Ann | Obama | null 6 | 5:6 | 5:4 | null | Natasha | null | Obama ---+-----+--------+----------+-----------+-----------+-----7 item(s) found. Query executed in 0.038 sec(s). With the result-set ready, display record number four in the result-set, (for M alia Ann Obama): orientdb> DISPLAY RECORD 5 -----------------------------------------------------------------------Class: Person id: 5:5 v.0 -----------------------------------------------------------------------parent : Person@5:4{parent:null,children:[Person@5:5, Person@5:6], name:Barack,surname:Obama,city:City@-6:2} children : null name : Malia Ann surname : Obama city : null ------------------------------------------------------------------------ For more information on other commands, see Console Commands. 299 Console Console - DISPLAYS RAW RECORD Displays details on the given record from the last returned result-set in a binary format. S yntax DISPLAY RAW RECORD Defines the relative position of the record in the last result-set. Example Query the database on the class V to generate a result-set: orientdb {db=GratefulDeadConcerts}> SELECT song_type, name, performances FROM V LIMIT 6 -----+-------+--------+----------+-------------------------+-------------# | @RID | @CLASS | song_type | name | performances -----+-------+--------+----------+-------------------------+-------------0 | #9:1 | V | cover | HEY BO DIDDLEY | 5 1 | #9:2 | V | cover | IM A MAN | 1 2 | #9:3 | V | cover | NOT FADE AWAY | 531 3 | #9:4 | V | original | BERTHA | 394 4 | #9:5 | V | cover | GOING DOWN THE ROAD... | 293 5 | #9:6 | V | cover | MONA | 1 6 | #9:7 | V | null | Bo_Diddley | null -----+-------+--------+-----------+------------------------+------------LIMIT EXCEEDED: resultset contains more items not displayed (limit=6) 6 item(s) found. Query executed in 0.136 sec(s). Display raw record on the song "Hey Bo Diddley" from the result-set: orientdb {db=GratefulDeadConcerts}> DISPLAY RAW RECORD 0 Raw record content. The size is 292 bytes, while settings force to print first 150 bytes: ^@^BV^Rsong_type^@^@^@^G^Hname^@^@^@^G^Htype^@^@^@ ^G^Xperformances^@^@^@ ^A^^out_followed_by^@^@^@ ^V^\out_written)by^@^@^@ ^V^Vout_sung_by^@^@^@ ^V^\in_followed_by^@^@^@ ^V^@civer^\HEY Bo D For more information on other commands available, see Console Commands. 300 Console Console - DROP DATABASE Removes a database completely. If the database is open and a database name not given, it removes the current database. S yntax DROP DATABASE [ ] Defines the server user. This user must have the privileges to drop the database. Defines the password for the server user. NOTE: When you drop a database, it deletes the database and all records, caches and schema information it contains. Unless you have made backups, there is no way to restore the database after you drop it. Examples Remove the current local database: orientdb> DROP DATABASE Remove the database orientdb> demo at localhost: DROP DATABASE REMOTE:localhost/demo root root_password You can create a new database using the DATABASE CREATE DATABASE command. To make changes to an existing database, use the ALTER command. For more information on other commands, please refer to Console Commands and SQL Commands. 301 Console Console - DROP SERVER USER Removes a user from the server. In order to do so, the current system user running the Console, must have permissions to write to the $ORIENTDB_HOME/config/orientdb-server-config.xmL configuration file. S yntax DROP SERVER USER Defines the user you want to drop. NOTE: For more information on server users, see OrientDB Server Security. This feature was introduced in version 2.2. Example Remove the user orientdb> editor from the Server: DROP SERVER USER editor Server user 'editor' dropped correctly To view the current server users, see the USER LIST SERVER USERS command. To create or update a server user, see the SET SERVER command. For more information on other commands, see Console Commands. 302 Console Console - EXPORT Exports the current database to a file. OrientDB uses a JSON-based Export Format. By default, it compresses the file using the GZIP algorithm. With the IMPORT command, this allows you to migrate the database between different versions of OrientDB without losing data. If you receive an error about the database version, export the database using the same version of OrientDB that has generated the database. Bear in mind, exporting a database browses it, rather than locking it. While this does mean that concurrent operations can execute during the export, it also means that you cannot create an exact replica of the database at the point when the command is issued. In the event that you need to create a snapshot, use the BACKUP You can restore a database from an export using the command. IMPORT . NOTE: While the export format is JSON, there are some constraints in the field order. Editing this file or adjusting its indentation may cause imports to fail. S yntax By default, this command exports the full database. Use its options to disable the parts you don't need to export. EXPORT DATABASE [-excludeAll] [-includeClass=*] [-excludeClass=*] [-includeCluster=*] [-excludeCluster=*] [-includeInfo=] [-includeClusterDefinitions=] [-includeSchema=] [-includeSecurity=] [-includeRecords=] [-includeIndexDefinitions=] [-includeManualIndexes=] [-compressionLevel=<0-9>] [-compressionBuffer=] Defines the path to the output file. -excludeAll Sets the export to exclude everything not otherwise included through command options Export includes certain classes, specifically those defined by a space-separated list.In case you specify multiple -includeClass class names, you have to wrap the list between quotes, eg. -includeClass="Foo Bar Baz" Export excludes certain classes, specifically those defined by a space-separated list. -excludeClass -includeCluster Export includes certain clusters, specifically those defined by a space-separated list. -excludeCluster Export excludes certain clusters, specifically those defined by a space-separated list. -includeInfo Defines whether the export includes database information. -includeClusterDefinitions -includeSchema Defines whether the export includes the database schema. Defines whether the export includes database security parameters. -includeSecurity -includeRecords Defines whether the export includes cluster definitions. Defines whether the export includes record contents. -includeIndexDefinitions -includeManualIndexes -compressionLevel Defines whether the export includes the database index definitions. Defines whether the export includes manual index contents. Defines the compression level to use on the export, in a range between (maximum compression). The default is -compressionBuffer 1 0 (no compression) and 9 . (Feature introduced in version 1.7.6.) Defines the compression buffer size in bytes to use in compression. The default is 16kb. (Feature introduced in version 1.7.6.) Examples Export the current database, including everything: 303 Console orientdb> EXPORT DATABASE C:\temp\petshop.export Exporting current database to: C:\temp\petshop.export... Exporting database info...OK Exporting dictionary...OK Exporting schema...OK Exporting clusters... - Exporting cluster 'metadata' (records=11) -> ...........OK - Exporting cluster 'index' (records=0) -> OK - Exporting cluster 'default' (records=779) -> OK - Exporting cluster 'csv' (records=1000) -> OK - Exporting cluster 'binary' (records=1001) -> OK - Exporting cluster 'person' (records=7) -> OK - Exporting cluster 'animal' (records=5) -> OK - Exporting cluster 'animalrace' (records=0) -> OK - Exporting cluster 'animaltype' (records=1) -> OK - Exporting cluster 'orderitem' (records=0) -> OK - Exporting cluster 'order' (records=0) -> OK - Exporting cluster 'city' (records=3) -> OK Export of database completed. Export the current database, including only its functions: orientdb> EXPORT DATABASE functions.gz -includeClass=OFunction -includeInfo=FALSE -includeClusterDefinitions=FALSE -includeSchema=FALSE -includeIndexDefinitions=FALSE -includeManualIndexes=FALSE Alternatively, you can simplify the above by excluding all, then including only those features that you need. For instance, export the current database, including only the schema: orientdb> EXPORT DATABASE schema.gz -excludeALL -includeSchema=TRUE For more information on backups and restores, imports and exports, see the following commands: IM PORT DATABASE BACKUP DATABASE RESTORE DATABASE as well as the following pages: Export File Format ODatabaseExport Java Class For more information on other commands, see Console Commands. 304 Console Console - EXPORT RECORD Exports the current record, using the requested format. In the event that you give a format that OrientDB does not support, it provides a list of supported formats. S yntax EXPORT RECORD Defines the export format you want to use. Examples Use SELECT to create a record for export: orientdb> SELECT name, surname, parent, children, city FROM Person WHERE name='Barack' AND surname='Obama' ---+-----+--------+---------+--------+------------+-----# | RID | name | surname | parent | children | city ---+-----+--------+---------+--------+------------+-----0 | 5:4 | Barack | Obama | null | [5:5, 5:6] | -6:2 ---+-----+--------+---------+--------+------------+------ Export JSON data from this record: orientdb> EXPORT RECORD JSON { 'name': 'Barack', 'surname': 'Obama', 'parent': null, 'children': [5:5, 5:6], 'city': -6:2 } Use a bad format value to determine what export formats are available on your database: orientdb> EXPORT RECORD GIBBERISH ERROR: Format 'GIBBERISH' was not found. Supported formats are: - json - ORecordDocument2csv For more information on other commands, see Console Commands. 305 Console Console - FREEZE DATABASE Flushes all cached content to disk and restricts permitted operations to read commands. With the exception of reads, none of the commands made on a frozen database execute. It remains in this state until you run the RELEASE command. Executing this command requires server administration rights. You can only execute it on remote databases. If you would like to freeze or release a local database, use the ODatabase.freeze() and ODatabase.release() methods directly through the OrientDB API. You may find this command useful in the event that you would like to perform backups on a live database. To do so, freeze the database, perform a file system snapshot, then release the database. You can now copy the snapshot anywhere you want. This works best when the backup doesn't take very long to run. S yntax FREEZE DATABASE Example Freezes the current database: orientdb> FREEZE DATABASE To unfreeze a database, use the RELEASE DATABASE command. For more information on other commands, please refer to Console Commands and SQL Commands. 306 Console Console - GET Returns the value of the requested property. S yntax GET Defines the name of the property. Example Find the default limit on your database: orientdb> GET LIMIT limit = 20 To display all available properties configured on your database, use the PROPERTIES command. For more information on other commands, see Console Commands. 307 Console Console - IMPORT Imports an exported database into the current one open. Import process doesn't lock the database, so any concurrent operations are allowed, but they could interfer in the import process causing errors. The input file must use the JSON Export Format, as generated by the EXPORT command. By default, this file is compressed using the GZIP algorithm. With EXPORT , this command allows you to migrate between releases without losing data, by exporting data from the old version and importing it into the new version. S yntax IMPORT DATABASE [-format = ] [-preserveClusterIDs = ] [-deleteRIDMapping = ] [-merge = ] [-migrateLinks = ] [-rebuildIndexes = ] Is the input file format. If not specified, OrientDB tries to recognize it. The available formats are (since v2.2.8): orientdb, the OrientDB export file format graphml, for Graph XM L graphson, for Graph JSON Defines the path to the file you want to import. -preserveClusterIDs Defines whether you want to preserve cluster ID's during the import. When turned off, the import creates temporary cluster ID's, which can sometimes fail. This option is only valid with PLocal storage. Defines whether you want to preserve the dictionary index used by the import to map old RIDs to new RIDs. -deleteRIDMapping The index name is -merge ___exportImportRIDMap and you could use in your application. By default the index is removed after the import. Defines whether you want to merge the import with the data already in the current database. When turned off, the default, the import overwrites current data, with the exception of security classes, ( ORole , OUser , OIdentity ), which it always preserves. This feature was introduced in version 1.6.1. -migrateLinks Defines whether you want to migrate links after the import. When enabled, this updates all references from the old links to the new Record ID's. By default, it is enabled. Advisable that you only turn it off when merging and you're certain no other existent records link to those you're importing. This feature was introduced in version 1.6.1. -rebuildIndexes Defines whether you want to rebuild indexes after the import. By default, it does. You can set it to false to speed up the import, but do so only when you're certain the import doesn't affect indexes. This feature was introduced in version 1.6.1. Example Import the database petshop.export : 308 Console orientdb> IMPORT DATABASE C:/temp/petshop.export -preserveClusterIDs=true Importing records... - Imported records into the cluster 'internal': 5 records - Imported records into the cluster 'index': 4 records - Imported records into the cluster 'default': 1022 records - Imported records into the cluster 'orole': 3 records - Imported records into the cluster 'ouser': 3 records - Imported records into the cluster 'csv': 100 records - Imported records into the cluster 'binary': 101 records - Imported records into the cluster 'account': 1005 records - Imported records into the cluster 'company': 9 records - Imported records into the cluster 'profile': 9 records - Imported records into the cluster 'whiz': 1000 records - Imported records into the cluster 'address': 164 records - Imported records into the cluster 'city': 55 records - Imported records into the cluster 'country': 55 records - Imported records into the cluster 'animalrace': 3 records - Imported records into the cluster 'ographvertex': 102 records - Imported records into the cluster 'ographedge': 101 records - Imported records into the cluster 'graphcar': 1 records For more information on backups, restores, and exports, see: ODatabaseImport BACKUP , RESTORE and EXPORT commands, and the Java class. For the JSON format, see Export File Format. For more information on other commands, see Console Commands. Troubleshooting Validation Errors Occasionally, you may encounter validation errors during imports, usually shown as an with version 2.2, you can disable validation at the database-level using the OValidationException ALTER DATABASE exception. Beginning command, to allow the import to go through. 1. Disable validation for the current database: orientdb> ALTER DATABASE validation false 2. Import the exported database: orientdb> IMPORT DATABASE /path/to/my_data.export -preserveClusterIDs=TRUE 3. Re-enable validation: orientdb> ALTER DATABASE validation true Cluster ID's During imports you may occasionally encounter an error that reads: Imported cluster 'XXX' has id=6 different from the original: 5 Typically occurs in databases that were created in much older versions of OrientDB. You can correct it using the class ORIDs DROP CLASS . on the , then attempting the import again. 1. Import the database: 309 Console orientdb> IMPORT DATABASE /path/to/old_data.export Importing records... - Creating cluster 'company'...Error on database import happened just before line 16, column 52 com.orientechnologies.orient.core.exception.OConfigurationException: Imported cluster 'company has id=6 different from the original: 5 at com.orientechnologies.orient.core.db.tool.ODatabaseImport.importClusters( ODatabaseImport.java:500) at com.orientechnologies.orient.core.db.tool.ODatabaseIMport.importDatabase( ODatabaseImport.java:121) 2. Drop the class: ORIDs orientdb> DROP CLASS ORIDs 3. Import the database: orientdb> IMPORT DATABASE /path/to/old_data.export The database now imports without error. 310 Console Console - INDEXES Displays all indexes in the current database. S yntax INDEXES Example Display indexes in the current database: orientdb {db=GratefulDeadConcerts}> INDEXES INDEXES --------------+------------+-------+--------+--------NAME | TYPE | CLASS | FIELDS | RECORDS --------------+------------+-------+--------+--------dictionary | 0 Group.Grp_Id | UNIQUE | DICTIONARY | | Group | Grp_Id | | 1 ORole.name | UNIQUE | ORole | name | 3 OUser.name | UNIQUE | OUser | name | 4 --------------+------------+----------------+--------TOTAL = 4 8 ------------------------------------------------------ For more information on other commands, see Console Commands. 311 Console Console - INFO Displays all information on the current database. S yntax INFO Example Display information on database petshop orientdb {db=petshop}> : INFO Current database: ../databases/petshop/petshop CLUSTERS: ------------+------+----------+---------NAME | ID | TYPE | ELEMENTS ------------+------+----------+---------metadata | 0 | Physical | 11 index | 1 | Physical | 0 default | 2 | Physical | 779 csv | 3 | Physical | 1000 binary | 4 | Physical | 1001 person | 5 | Physical | 7 animal | 6 | Physical | 5 animalrace | -2 | Logical | 0 animaltype | -3 | Logical | 1 orderitem | -4 | Logical | 0 order | -5 | Logical | 0 city | -6 | Logical | 3 ------------+------+----------+---------TOTAL 2807 ----------------------------------------CLASSES: ------------+----+------------+---------NAME | ID | CLUSTERS | ELEMENTS ------------+----+------------+---------Person | 0 | person | 7 Animal | 1 | animal | 5 AnimalRace | 2 | AnimalRace | 0 AnimalType | 3 | AnimalType | 1 OrderItem | 4 | OrderItem | 0 Order | 5 | Order | 0 City | 6 | City | 3 ------------+----+------------+---------TOTAL 16 ----------------------------------------- For more information on other commands, see Console Commands. 312 Console Console - INFO CLASS Displays all information on givne class. S yntax INFO CLASS Defines what class you want information on. Example Display information on class orientdb> Profile INFO CLASS Profile Default cluster......: profile (id=10) Supported cluster ids: [10] Properties: --------+----+----------+-----------+---------+-----------+----------+-----+---NAME | ID | TYPE | LINK TYPE | INDEX | MANDATORY | NOT NULL | MIN | MAX --------+----+----------+-----------+---------+-----------+----------+-----+---nick | 3 | STRING | null | | false | false | 3 | 30 name | 2 | STRING | null |NOTUNIQUE| false | false | 3 | 30 surname| 1 | STRING | null | | false | false | 3 | 30 | ... | ... | ... | ... | ... |... | ... | | false | false | | ... | photo | 0 | TRANSIENT| null --------+----+----------+-----------+---------+-----------+----------+-----+---- For more information on other commands, see Console Commands. 313 Console Console - INFO PROPERTY Displays all information on the given property. S yntax INFO PROPERTY . Defines the class to which the property belongs. Defines the property you want information on. Example Display information on the property orientdb> name in the class OUser : INFO PROPERTY OUser.name PROPERTY 'OUser.name' Type.................: STRING Mandatory............: true Not null.............: true Read only............: false Default value........: null Minimum value........: null Maximum value........: null REGEXP...............: null Collate..............: {OCaseInsensitiveCollate : name = ci} Linked class.........: null Linked type..........: null INDEXES (1 altogether) --------------------+-----------NAME | PROPERTIES --------------------+-----------OUser.name | name --------------------+------------ For more information on other commands, see Console Commands. 314 Console Console - JS Executes commands in the Javascript language from the Console. Look also Javascript Command. S yntax JS Defines the commands you want to execute. Interactive Mode You can execute a command in just one line ( executing JS JS print('Hello World!') ) or enable the interactive input by just and then typing the Javascript expression as multi-line inputs. It does not execute the command until you type Bear in mind, the end end . here is case-sensitive. Examples Execute a query and display the result: orientdb> js [Started multi-line command. Type just 'end' to finish and execute.] orientdb> var r = db.query('select from ouser'); orientdb> for(var i=0;i orientdb> print( r[i] ); orientdb> } orientdb> end OUser#5:0{roles:[1],status:ACTIVE,password:{PBKDF2WithHmacSHA256}C08CE0F5160EA4050B8F10EDBB86F06EB0A2EE82DF73A340:BC1B604 0727C1E11E3A961A1B2A49615C96938710AF17ADD:65536,name:admin} v1 OUser#5:1{name:reader,password:{PBKDF2WithHmacSHA256}41EF9B675430D215E0970AFDEB735899B6665DF44A29FE98:5BC48B2D20752B12B5E 32BE1F22C6C85FF7CCBEFB318B826:65536,status:ACTIVE,roles:[1]} v1 OUser#5:2{name:writer,password:{PBKDF2WithHmacSHA256}FA0AD7301EA2DB371355EB2855D63F4802F13858116AB82E:18B8077E1E63A45DB0A 3347F91E03E4D2218EA16E5100105:65536,status:ACTIVE,roles:[1]} v1 Client side script executed in 0.142000 sec(s). Value returned is: null For more information on the Javascript execution, see Javascript Command. For more information on other commands, see Console Commands. 315 Console Console - JSS Executes commands on OrientDB Server in the Javascript language from the Console. Look also Javascript Command. S yntax JSS Defines the commands you want to execute. Interactive Mode You can execute a command in just one line ( executing JSS JSS print('Hello World!') ) or enable the interactive input by just and then typing the Javascript expression as multi-line inputs. It does not execute the command until you type Bear in mind, the end end . here is case-sensitive. Examples Execute a query and display the result: orientdb> jss [Started multi-line command. Type just 'end' to finish and execute.] orientdb> var r = db.query('select from ouser'); orientdb> for(var i=0;i orientdb> print( r[i] ); orientdb> } orientdb> end Server side script executed in 0.146000 sec(s). Value returned is: null In this case the output will be displayed on the server console. For more information on the Javascript execution, see Javascript Command. For more information on other commands, see Console Commands. 316 Console Console - LIST DATABASES Displays all databases hosted on the current server. Note that this command requires you connect to the OrientDB Server. S yntax LIST DATABASES Example Connect to the server: orientdb> CONNECT REMOTE:localhost admin admin_password List the databases hosted on the server: orientdb {server=remote:localhost/}> LIST DATABASES Found 4 databases: * ESA (plocal) * Napster (plocal) * Homeland (plocal) * GratefulDeadConcerts (plocal) For more information on other commands, see Console Commands. 317 Console Console - LIST CONNECTIONS Displays all active connections to the OrientDB Server. Command introduced in version 2.2. The connections as per server, so you should connect to the server, not to the database. S yntax LIST CONNECTIONS Permissions In order to enable a user to execute this command, you must add "server.info" as resource to the server user. Example List the current connections to the OrientDB Server: orientdb {server=remote:localhost/}> LIST CONNECTIONS ---+----+--------------+------+-------------------+--------+-----+--------+-------# | ID |REMOTE_ADDRESS|PROTOC|LAST_OPERATION_ON |DATABASE|USER |COMMAND |TOT_REQS ---+----+--------------+------+-------------------+--------+-----+--------+-------0 | 17 |/127.0.0.1 |binary|2015-10-12 19:22:34|- |- |info | 1 1 | 16 |/127.0.0.1 |binary|1970-01-01 01:00:00|- |- |- | 0 5 | 1 |http |admin|Listen | 32 |/127.0.0.1 |1970-01-01 00:59:59|pokec ---+----+--------------+------+-------------------+--------+-----+--------+-------- For more information on other commands, see Console Commands. 318 Console Console - LOAD RECORD Loads a record the given Record ID from the current database. S yntax LOAD RECORD #5:5 : LOAD RECORD #5:5 -------------------------------------------------------------------------------Class: Person id: #5:5 v.0 -------------------------------------------------------------------------------parent : Person@5:4{parent:null,children:[Person@5:5, Person@5:6],name:Barack, surname:Obama,city:City@-6:2} children : null name : Malia Ann surname : Obama city : null -------------------------------------------------------------------------------- For more information on other commands, see Console Commands. 319 Console Console - LOAD SCRIPT (from 2.2.18) Loads a sql script from the given path and executes it. S yntax LOAD SCRIPT

Navigation menu