Share your code. npm Orgs help your team discover, share, and reuse code. Create a free org »



    Neode is a Neo4j OGM for Node JS designed to take care of the CRUD boilerplate involved with setting up a neo4j project with Node. Just install, set up your models and go.

    Getting Started


    npm install --save neode


    // index.js
    import Neode from 'neode';
    const instance = new Neode('bolt://localhost:7687', 'username', 'password');

    Enterprise Mode

    To initiate Neode in enterprise mode and enable enterprise features, provide a true variable as the fourth parameter.

    // index.js
    import Neode from 'neode';
    const instance = new Neode('bolt://localhost:7687', 'username', 'password', true);

    Usage with .env variables

    npm i --save dotenv
    // .env
    // index.js
    import Neode from 'neode';
    const instance = new Neode.fromEnv();

    Loading with Models

    You can use the with() method to load multipe models at once.

    const neode = require('neode')
            Movie: require('./models/Movie'),
            Person: require('./models/Person')

    Load from Directory

    You can load a directory of models by calling the withDirectory() method.

    // models/Person.js
    module.exports = {
      id: {
        type: 'uuid',
        primary: true
      name: 'string'
    // index.js

    Defining a Node Definition

    Neode revolves around the notion of node definitions, or Models. To interact with the graph, you will need to define a node, identified by a name and with a schema of properties.

    instance.model(name, schema);

    Schema Object

    instance.model('Person', {
        person_id: {
            primary: true,
            type: 'uuid',
            required: true, // Creates an Exists Constraint in Enterprise mode
        payroll: {
            type: 'number',
            unique: 'true', // Creates a Unique Constraint
        name: {
            type: 'name',
            indexed: true, // Creates an Index
        age: 'number' // Simple schema definition of property : type
    Property Types
    • string
    • number
      • int
      • float
    • boolean
    • relationship
      • type
      • relationship: Neo4j relationship type
      • target: node definition
      • properties: schema

    Validation is provided by Joi. Certain data types (float, integer, boolean) will also be type cast.

    • required
    • string
      • min
      • max
    • number
      • min
      • max

    Defining Relationships

    Relationships can be created in the schema or defined retrospectively.

    instance.model(label).relationship(type, relationship, direction, label, schema);
    instance.model('Person').relationship('knows', 'KNOWS', 'out', 'Person', {
        since: {
            type: 'number',
            required: true,
        defaulted: {
            type: 'string',
            default: 'default'

    Eager Loading

    You can eager load relationships in a findAll() call by setting the eager property inside the relationship schema to true.

        acts_in: {
            type: "relationship",
            target: "Movie",
            relationship: "ACTS_IN",
            direction: "out",
            properties: {
                name: "string"
            eager: true // <-- eager load this relationship

    Eager loaded relationships can be retrieved by using the get() method. A NodeCollection instance will be returned.

    const person = person.find({name: "Tom Hanks"})
    const movies = person.get('acts_in');
    const first = movies.first();

    Extending a Schema definition

    You can inherit the schema of a class and extend by calling the extend method.

    instance.extend(original, new, schema)
    instance.extend('Person', 'Actor', {
        acts_in: {
            type: "relationship",
            target: "Movie",
            relationship: "ACTS_IN",
            direction: "out",
            properties: {
                name: "string"


    Running a Cypher Query

    instance.cypher(query, params)
    instance.cypher('MATCH (p:Person {name: {name}}) RETURN p', {name: "Adam"})
        .then(res => {

    Running a Batch

    Batch queries run within their own transaction. Transactions can be sent as either a string or an object containing query and param propertes.

        {query: 'CREATE (p:Person {name: {name}}) RETURN p', params: {name: "Adam"}},
        {query: 'CREATE (p:Person {name: {name}}) RETURN p', params: {name: "Joe"}},
        {query: 'MATCH (first:Person {name: {first_name}}), (second:Person {name:{second_name}}) CREATE (first)-[:KNOWS]->(second)', params: {name: "Joe"}}
        .then(res => {

    Get all Nodes

    instance.all(label, properties)
    instance.all('Person', {name: 'Adam'}, {name: 'ASC', id: 'DESC'}, 1, 0)
        .then(collection => {
            console.log(collection.length); // 1
            console.log(collection.get(0).get('name')); // 'Adam'

    Get Node by Internal Node ID

    instance.findById(label, id)
    instance.findById('Person', 1)
        .then(person => {
            console.log(; // 1

    Get Node by Primary Key

    Neode will work out the model's primary key and query based on the supplied value.

    instance.find(label, id)
    instance.find('Person', '1234')
        .then(res => {...});

    First by Properties

    Using a key and value

    instance.first(label, key, value)
    instance.first(label).first(key, value)
    instance.first('Person', 'name', 'Adam')
        .then(adam => {...})

    Using multiple properties

    instance.first(label, properties)
    instance.first('Person', {name: 'Adam', age: 29})
        .then(adam => {...})


    Creating a Node

    instance.create(label, properties);
    instance.create('Person', {
        name: 'Adam'
    .then(adam => {
        console.log(adam.get('name')); // 'Adam'

    Merging a Node

    Nodes are merged based on the indexes and constraints.

    instance.merge(label, properties);
    instance.merge('Person', {
        person_id: 1234,
        name: 'Adam',

    Merge On Specific Properties

    If you know the properties that you would like to merge on, you can use the mergeOn method.

    instance.mergeOn(label, match, set);
    instance.model(label).mergeOn(match, set);
    instance.mergeOn('Person', {person_id: 1234}, {name: 'Adam'});

    Updating a Node

    You can update a Node instance directly by calling the update() method.

    instance.create('Person', {name: 'Adam'})
        .then(adam => adam.update({age: 29}));

    Creating a Relationships

    You can relate two nodes together by calling the relateTo() method.

    model.relateTo(other, type, properties)
        instance.create('Person', {name: 'Adam'}),
        instance.create('Person', {name: 'Joe'})
    .then(([adam, joe]) => {
        adam.relateTo(joe, 'knows', {since: 2010})
            .then(res => {
                console.log(rel.from().get('name'), ' has known ','name'), 'since', rel.get('since'));  // Adam has known Joe since 2010

    Note: when creating a relationship defined as in (DIRECTION_IN), from from() and to() properties will be inversed regardless of which model the relationship is created by.

    Deleting a node

    You can delete a Node instance directly by calling the delete() method.

    instance.create('Person', {name: 'Adam'})
      .then(adam => adam.delete());

    Cascade Deletion

    While deleting a Node with the delete() method, you can delete any dependant nodes or relationships. For example, when deleting a Movie you may also want to remove any reviews but keep the actors.

    You cna do this by setting the cascade property of a relationship to "delete" or "detach". "delete" will remove the node and relationship by performing a DETACH DELETE, while "detach" will simply remove the relationship, leaving the node in the graph.

    // Movie.js
    module.exports = {
      // ...
      ratings: {
        type: 'relationship',
        'relationship': 'RATED',
        direction: 'IN',
        target: 'User',
        'cascade': 'delete'
      actors: {
        type: 'relationship',
        'relationship': 'ACTS_IN',
        direction: 'IN',
        target: 'Actor',
        'cascade': 'detach'

    Note: Attempting to delete a Node without first removing any relationships will result in an error.

    Deleting a set of nodes


    instance.delete(label, where)
    instance.delete('Person', {living: false});

    Deleting all nodes of a given type

      .then(() => console.log('Everyone has been deleted'));

    Query Builder

    Neode comes bundled with a query builder. You can create a Query Builder instance by calling the query() method on the Neode instance.

    const builder = instance.query();

    Once you have a Builder instance, you can start to defining the query using the fluent API.

    builder.match('p', 'Person')
        .where('', 'Adam')

    For query examples, check out the Query Builder Test suite.

    Building Cypher

    You can get the generated cypher query by calling the build() method. This method will return an object containing the cypher query string and an object of params.

    const {query, params} =;
    instance.query(query, params)
        .then(res => {

    Executing a Query

    You can execute a query by calling the execute() method on the query builder.

    builder.match('this', 'Node')
        .whereId('this', 1)
        .then(res => {


    Neode will install the schema created by the constraints defined in your Node definitions.

    Installing the Schema

        .then(() => console.log('Schema installed!'))

    Note: exists constraints will only be created when running in enterprise mode. Attempting to create an exists constraint on Community edition will cause a Neo.DatabaseError.Schema.ConstraintCreationFailed to be thrown.

    Dropping the schema

    Dropping the schema will remove all indexes and constraints created by Neode. All other indexes and constraints will be left intact.

        .then(() => console.log('Schema dropped!'))


    • 3.3

      • Routing policies and countries for CC
      • Set pool size
      • Read & Write sessions/transactions
      • Encryption
    • Relationships

      • Relationship Constraints
      • Delete dependencies when deleting a node beyond the first degree
    • Schema

      • Composite indexes
    • Query Builder

      • More where clauses
      • CREATE
      • SET
      • DELETE
      • Match Relationship
      • Match path
    • Housekeeping

      • Tests/Code Coverage


    npm i neode

    Downloadsweekly downloads








    last publish


    • avatar