Nietzsche's Preposterous Moustache
    Share your code. npm Orgs help your team discover, share, and reuse code. Create a free org »

    sails-orientdbpublic

    npm version Build Status Test Coverage dependencies Gitter

    sails-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-schema v0.10.19, a dependency of waterline, breaks sails-orientdb tests. As such we recommend using sails-orientdb with waterline <= 0.10.27 / waterline-schema <= 0.1.18. More about this on issue #152.

    sails-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 or use 'create' to only create new collections/attributes.

    Sails-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 sails-orientdb supports Semantic, Queryable, Associations, Migratable and SQL interfaces. Sails-orientdb complies with waterline API and it's used in the same way as other waterline/sails adapters.

    Sails-orientdb connects to OrientDB using OrientJS (OrientDB's official driver).

    Table of Contents

    1. Installation
    2. Configuration
    3. Overview
    4. Usage
    5. Testing
    6. Issues or Suggestions
    7. History
    8. Authors
    9. About Waterline
    10. License

    Installation

    Install stable version from NPM:

    npm install sails-orientdb --save

    Install edge version from GitHub (mostly for testing):

    npm install appscot/sails-orientdb

    Configuration

    Sails-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/sails-orientdb with frameworks such as Express look in the example folder.

    Waterline v0.10.x configuration

    Basic Example

    var orientAdapter = require('sails-orientdb');
    var config = {
      adapters: {
        'default': orientAdapter,
        orient: orientAdapter,
      },
      
      connections: {
        myLocalOrient: {
          adapter: 'orient',
          host: 'localhost',
          port: 2424,
          user: 'root',
          password: 'root',
          database: 'waterline'
        }
      },
      
      defaults: {
        // The first time you run sails-orientdb `migrate` needs to be set to 'drop', 'alter' or 'create' in order to create the DB schema 
        // More about this on: http://sailsjs.org/#!/documentation/concepts/ORM/model-settings.html 
        migrate: 'safe'
      }
    }

    Connection advanced config example

        myLocalOrient: {
          adapter: 'orient',
          host: 'localhost',
          port: 2424,
          user: 'root',
          password: 'root',
          database: 'waterline',
          schema : true,
          
          // Additional options 
          options: {
          
            // DB/Oriento Options 
            // 
            // database type: graph | document 
            databaseType : 'graph',
            // 
            // storage type: memory | plocal 
            storage : 'plocal',
            
            // Useful in REST APIs 
            // 
            // If `id` is URI encoded, decode it with `decodeURIComponent()` (useful when `id` comes from an URL) 
            decodeURIComponent : true,
            // 
            // Replaces circular references with `id` after populate operations (useful when results will be JSONfied) 
            removeCircularReferences : false,
            
            // migrations 
            // 
            // Drop tables without deleting edges/vertexes hence not ensuring graph consistency 
            // Will speed up drop operations. Only works with migration: 'alter' or 'drop' 
            unsafeDrop : false,
            
            // other 
            // 
            // Turn parameterized queries on 
            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 Sails-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 sails-orientdb represent each kind of association in an OrientDB database.

    One-to-One Associations

    For One-to-One Associations sails-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 sails-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. Sails-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. Sails-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)

    Sails-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 sails-orientdb/waterline check the Waterline Documentation.

    For a SailsJS/OrientDB tutorial check Chris' Creating an application with SailsJS and OrientDB on your Mac.

    Below we describe how sails-orientdb approaches and adds to the waterline core experience.

    Models

    sails-orientdb uses the standard waterline model definition and extends it in order to accommodate OrientDB features.

    Indexes

    To add an index to an attribute the keyword index is used as per the waterline default model definition:

    attributes: {
      email: {
        type: 'string',
        index: true  // will default to SB-Tree NOTUNIQUE 
      }
    }

    However OrientDB supports other indexes and it's possible to use them by specifying the name of the index type as a string in the index key. Example:

    attributes: {
      email: {
        type: 'string',
        index: 'fulltext_hash_index'
      }
    }

    List of supported index types:

    • unique
    • notunique
    • fulltext
    • dictionary
    • unique_hash_index
    • notunique_hash_index
    • fulltext_hash_index
    • dictionary_hash_index

    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 sails-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 supports all waterline standard query methods and extends it 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:

    // Assume a model named "Friend" 
    Friend.query("SELECT FROM friendTable WHERE name='friend query'", function(err, retrievedUsers){
        console.log(retrievedUsers);
    });
     
    // Using params (and promise) 
    Friend.query("SELECT FROM friendTable WHERE name=:name", {
      params: {
        name: 'friend query'
      }
    }).then(function(retrievedUsers){
        console.log(retrievedUsers);
    }).catch(function(err){
      console.error(err);
    });

    .native ()

    Returns a native Oriento class

    usage:

    // Assume a model named "Post" 
    Post.native()
        .property.list()
      .then(function (properties) {
        console.log('The class has the following properties:', properties);
      });

    .getDB ()

    Returns a native Oriento database object

    usage:

    // Assume a model named "Post" 
    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:

    // Assume a model named "Post" 
    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:

    // Assume a model named "Post" 
    Post.runFunction('foo', 'arg1').from('OUser').limit(1).one()
      .then(function(res) {
        console.log(res.foo);  // res.foo contains the result of the function 
        });

    .createEdge (from, to, options, callback)

    Creates edge between specified two model instances by ID in the form parameters from and to

    usage:

    // Assume a model named "Post" 
    Post.createEdge('#12:1', '#13:1', { '@class':'Comments' }, function(err, result){
      console.log('Edge created', result);
    });
     
    // Adding param createdAt to the edge (and using promise) 
    Post.createEdge('#12:2', '#13:2', { '@class':'Comments', createdAt: new Date() })
    .then(function(result){
      console.log('Edge created', 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:

    // Assume a model named "Post" 
    Post.deleteEdges('#12:1', '#13:1', null, function(err, result){
      console.log('Edge deleted', 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.

    .increment (criteria, field[, amount][, cb])

    Increments the given field by amount (defaults to 1). This can be used to generate sequencial numbers, more about this in OrientDB docs.

    usage:

    // Given a model Counter with attributes `name` and `value` 
    Counter.increment({ name: 'counter1' }, 'value', function (err, counter) {
      console.log('counter1 has increased by 1 to:', counter.value);
    });
     
    // To decrement use negative numbers 
    Counter.increment({ name: 'counter1' }, 'value', -2)
    .then(function (counter) {
      console.log('counter1 haas decreased by 2 to:', counter.value);
    });

    .removeCircularReferences (object)

    Convenience method that replaces circular references with id when one is available, otherwise it replaces the object with string '[Circular]'.

    usage:

    //Assume a model named "Post" 
    var result = Post.removeCircularReferences(posts);
    console.log(JSON.stringify(result));  // it's safe to 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
    /**
     * Venue Model
     *
     * Join table between teams and associations
     */
    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
    /**
     * Team.js
     */
    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
    /**
     * Stadium.js
     */
    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 sails-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.

    History

    In July 2014, Srinath Janakiraman created the original sails-orientdb adapter.

    Almost simultaneously, Gaurav Dhiman created sails-orientdb-binary with support for both binary and REST protocol.

    In October 2014, Dário Marcelino forked sails-orientdb and created waterline-orientdb with improved support when used with waterline standalone and made the adapter pass all API integration tests.

    In March 2015, Srinath, Gaurav and Dário combined their efforts into maintaining a single adapter with the original name: sails-orientdb.

    Authors

    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

    install

    npm i sails-orientdb

    Downloadsweekly downloads

    35

    version

    0.10.60

    license

    MIT

    repository

    github.com

    last publish

    collaborators

    • avatar
    • avatar
    • avatar