waterline-orientdb
Waterline adapter for OrientDB. Waterline is an adapter-based ORM for Node.js with support for mysql, mongo, postgres, redis, orientdb and more.
Warning
waterline-orientdb
maps the logical id
attribute to the required @rid
physical-layer OrientDB Record ID.
Migrations
We don't recommend using migrate: 'alter'
as it has the nasty effect of deleting the data of all edges on a graphDB, leaving only data on the vertexes.
Either use 'safe'
and migrate manually or use 'drop'
to completely reset the data and collections. In production
always use 'safe'
. We are currently pushing for a new kind of migration strategy named 'create'
, check waterline issue #846.
Waterline-orientdb aims to work with Waterline v0.10.x and OrientDB v1.7.10 and later. While it may work with earlier versions, they are not currently supported, pull requests are welcome!
From the waterline adapter interfaces waterline-orientdb supports Semantic
, Queryable
, Associations
and Migratable
interfaces. Waterline-orientdb complies with waterline API and it's used in the same way as other waterline/sails adapters.
Waterline-orientdb connects to OrientDB using Oriento (OrientDB's official driver).
Table of Contents
- Installation
- Configuration
- Overview
- Usage
- Testing
- Issues or Suggestions
- Contributions
- About Waterline
- License
Installation
Install from NPM.
npm install waterline-orientdb --save
Configuration
Waterline-orientdb can be used with SailsJS, for more information on how to use Waterline in your Sails App view the Sails Docs.
An example configuration for SailsJS is provided here.
For examples on how to use Waterline/waterline-orientdb with frameworks such as Express look in the example folder.
Waterline v0.10.x configuration
Basic Example
var orientAdapter = require('waterline-orientdb');
var config = {
adapters: {
'default': orientAdapter,
orient: orientAdapter,
},
connections: {
myLocalOrient: {
adapter: 'orient',
host: 'localhost',
port: 2424,
user: 'root',
password: 'root',
database: 'waterline'
}
},
defaults: {
migrate: 'safe'
}
}
Connection advanced config example
myLocalOrient: {
adapter: 'orient',
host: 'localhost',
port: 2424,
user: 'root',
password: 'root',
database: 'waterline',
options: {
databaseType : 'graph',
storage : 'plocal',
decodeURIComponent : true,
removeCircularReferences : false,
unsafeDrop : false,
parameterized : true
}
}
The values stated above represent the default values. For an up to date comprehensive list check adapter.js.
Overview
Models
In a graph db Waterline-orientdb will represent most models in OrientDB as vertexes, the exception being Many-to-Many join tables which are represented by Edges. If using a document db, all models will be represented by documents.
Associations
To learn how to create associations with Waterline/Sails.js check the Waterline Docs Associations Page. Below we go through how waterline-orientdb represent each kind of association in an OrientDB database.
One-to-One Associations
For One-to-One Associations waterline-orientdb creates a LINK (OrientDB Types) to associate records.
One-to-Many Associations
One-to-Many Associations are also represented by LINKs in OrientDB.
Many-to-Many Associations
In many-to-many associations waterline-orientdb will connect vertexes using edges, hence edges act as join tables.
Custom edge names (optional)
Usually Waterline will create rather long names for join tables (e.g. driver_taxis__taxi_drivers) which are little meaningful from the perspective of a graphDB. Waterline-orientdb allows you to change the name of the edge by adding a property joinTableNames
to the dominant collection. Example:
{
identity: 'driver',
joinTableNames: {
taxis: 'drives'
},
attributes: {
name: 'string',
taxis: {
collection: 'taxi',
via: 'drivers',
dominant: true
}
}
}
In this example the join table name driver_taxis__taxi_drivers gets converted to drives. Complete example of the fixture can be found here.
Many-to-Many Through Associations
In a Many-to-Many Through Association (more info) the join table is represented in OrientDB by Edges. Waterline-orientdb automatically creates the edges whenever an association is created. The Edge is named after the property tableName (or identity in case tableName is missing).
Populate queries (joins)
Waterline-orientdb implements its own custom join function so when the user runs .populate(some_collection)
it will send a single SELECT
query with a fetchplan to OrientDB. This way join operations remain fast and performant by leveraging OrientDB's graphDB features.
Usage
Documentation
For a comprehensive reference on how to use waterline please check waterline-docs. Below we describe how waterine-orientdb
approaches and adds to the waterline core experience.
Models
waterline-orientdb
uses the standard waterline model definition and extends it in order to accommodate OrientDB features.
orientdbClass
It's possible to force the class of a model by adding the property orientdbClass
to the definition. Generally this is not required as waterline-orientdb
can determine which is the best class to use, so it should only be used in special cases. Possible values:
undefined
- the default and recommended option. The appropriate class will be determined for the model;""
or "document"
- class will be the default OrientDB document class;"V"
- class will be Vertex;"E"
- class will be Edge.
Example:
{
identity : 'post',
orientdbClass : 'V'
attributes : {
name : 'string'
}
}
Note, when using a document database (through config.options.databaseType
), orientdbClass
class will be ignored and all classes will be documents.
Methods
This adapter extends waterline with the following methods:
.query (query [, options], cb)
Runs a SQL query against the database using Oriento's query method. Will attempt to convert @rid's into ids.
usage:
Friend.query("SELECT FROM friendTable WHERE name='friend query'", function(err, retrievedUsers){
console.log(retrievedUsers);
});
Friend.query("SELECT FROM friendTable WHERE name=:name", {
params: {
name: 'friend query'
}
}, function(err, retrievedUsers){
console.log(retrievedUsers);
});
.native ()
Returns a native Oriento class
usage:
Post.native()
.property.list()
.then(function (properties) {
console.log('The class has the following properties:', properties);
});
.getDB ()
Returns a native Oriento database object
usage:
Post.getDB()
.class.list()
.then(function (classes) {
console.log('There are ' + classes.length + ' classes in the db:', classes);
});
.getServer ()
Returns a native Oriento connection
usage:
Post.getServer()
.list()
.then(function (dbs) {
console.log('There are ' + dbs.length + ' databases on the server.');
});
.runFunction (functionName [, ...])
Returns a prepared Oriento statement with query and params to run an OrientDB function.
usage:
Post.runFunction('foo', 'arg1').from('OUser').limit(1).one()
.then(function(res) {
console.log(res.foo);
});
.createEdge (from, to, options, callback)
Creates edge between specified two model instances by ID in the form parameters from
and to
usage:
Post.createEdge('#12:1', '#13:1', { '@class':'Comments' }, function(err, result){
console.log('Edges deleted', result);
});
Note: when using many-to-many or many-to-many through associations edges will automatically be created. This method is for manual edge manipulation only and it's not required for maintaining associations.
.deleteEdges (from, to, options, callback)
Deletes edges between specified two model instances by ID in the form parameters from
and to
usage:
Post.deleteEdges('#12:1', '#13:1', null, function(err, result){
console.log('Edge created', result);
});
Note: when using many-to-many or many-to-many through associations edges will automatically be deleted when using the conventional waterline methods. This method is for manual edge manipulation only and it's not required for maintaining associations.
.removeCircularReferences (object)
Convenience method that replaces circular references with id
when one is available, otherwise it replaces the object with string '[Circular]'.
usage:
var result = Post.removeCircularReferences(posts);
console.log(JSON.stringify(result));
Examples
For a vast set of examples on how to set up models take a look at waterline-adapter-tests fixtures, all of those are working examples and frequently tested.
The only case poorly covered is how to set up a Many-to-many through association as it is not yet officially supported. Below is an example of a Many-to-many through association that works in OrientDB.
Many-to-many through example
Venue model which will join (via edge) teams to stadiums
var Waterline = require('waterline');
module.exports = Waterline.Collection.extend({
tableName: 'venueTable',
identity: 'venue',
connection: 'associations',
attributes: {
seats: 'integer',
teamRef: {
columnName: 'teamRef',
type: 'string',
foreignKey: true,
references: 'team',
on: 'id',
onKey: 'id',
via: 'stadiumRef'
},
stadiumRef: {
columnName: 'stadiumRef',
type: 'string',
foreignKey: true,
references: 'stadium',
on: 'id',
onKey: 'id',
via: 'teamRef'
}
}
});
Team Model to be associated with Stadium model
var Waterline = require('waterline');
module.exports = Waterline.Collection.extend({
tableName: 'teamTable',
identity: 'team',
connection: 'associations',
attributes: {
name: 'string',
mascot: 'string',
stadiums: {
collection: 'Stadium',
through: 'venue',
via: 'team',
dominant: true
}
});
Stadium Model to be associated with Team model
var Waterline = require('waterline');
module.exports = Waterline.Collection.extend({
tableName: 'stadiumTable',
identity: 'stadium',
connection: 'associations',
attributes: {
name: 'string',
teams: {
collection: 'Team',
through: 'venue',
via: 'stadium'
}
}
});
An edge named venueTable will be created from Team to Stadium model instances whenever an instance of team model is saved with a 'stadiums' attribute.
Questions?
See FAQ.md
.
Testing
Test are written with mocha. Integration tests are handled by the waterline-adapter-tests project, which tests adapter methods against the latest Waterline API.
To run tests:
npm test
Issues or Suggestions
We are always trying to improve waterline-orientdb
either by fixing issues or adding new features. If you experienced an issue or have a suggestion feel free to raise a new issue, preferably by following the guidelines.
Contributions
We are always looking for the quality contributions! Please check the CONTRIBUTING.md for the contribution guidelines.
Thanks so much to Srinath Janakiraman (vjsrinath) who built the sails-orientdb
adapter, from which waterline-orientdb
was originally forked.
About Waterline
Waterline is a new kind of storage and retrieval engine.
It provides a uniform API for accessing stuff from different kinds of databases, protocols, and 3rd party APIs. That means you write the same code to get and store things like users, whether they live in OrientDB, Redis, mySQL, LDAP, MongoDB, or Postgres.
Waterline strives to inherit the best parts of ORMs like ActiveRecord, Hibernate, and Mongoose, but with a fresh perspective and emphasis on modularity, testability, and consistency across adapters.
License
MIT
© 2015 AppsCot