A very basic neo4j orm

Usage no npm install needed!

<script type="module">
  import vDocNeorm from 'https://cdn.skypack.dev/@v-doc/neorm';




A very simple neo4j javascript orm


npm install -S @jekel18/neorm


const { Sequence, Graph } = require('@jekel18/neorm)

Local build and test

npm run transpile
npm start



The Sequence object is used to represent a cypher pattern. For example the following pattern:


would be reprensent this way using the Sequence object

Sequence.node('Movie', 'n')

The node function allow two arguments: A descriptor and a tag. The tag is the name that will be use to identify the element inside the cypher query.

The descriptor can have multiple formats:

Sequence.node('Movie') // String representing a label
Sequence.node(['Movie', 'Person']) // Array of labels
const descriptor = {
    labels: ['Person'],
    born: 1954,
    name: 'Bob' 
Sequence.node(descriptor) // An object

To represent relationships, you can use the following method: relationship(descriptor, tag, direction).

Sequence.node('Person', 'person').relationship({labels: ['ACTED_IN'], 'rel', INCOMING).node('Movie', 'movie').relationship({labels: ['REVIEWED_BY'], 'rel', INCOMING).node('Person')

This would result in the following cypher

MATCH (person:Person)-[ACTED_IN]->(movie:Movie)<-[REVIEWD_BY]-(Person) RETURN person, movie
  • There is no limitation to the number of chained methods
  • Notice the how the tag arguments are used for the return statement of the cypher query
  • If the last method of the chain is a relationship, the pattern will be padded with an empty node

Conditional statement

A syntax similar to Mongoose and Sequelize can be used in the descriptor

const theMatrix = {
    title: { $or: ['The Matrix', 'The Matrix Reloaded']}
const actor = {
    labels: ['Person'],
    born: { $gte: 1960 }
const seq = Sequence.node(theMatrix, 'movies').relationship({labels: ['ACTED_IN'], 'rel', INCOMING).node(actor, 'actors');

Some operators can be used together:

// Find the actors born betweem 1950-1960 or 1970-1980
const theMatrix = {
    born: { $or: [ 
        { $and: [ { $gte: 1950 }, { $lte: 1960 } ] }, 
        { $and: [ { $gte: 1970 }, { $lte: 1980 } ] }, 

Those are the supported operator so far:

  • $or
  • $and
  • $lt
  • $lte
  • $gt
  • $gte


The Graph object is used to interact with the database.

Graph.connect('bolt://localhost', 'neo4j', 'mo49xw71');


var rel_def = { my_prop1: { $eq: 10}, my_array: { $eq: ['hi', 'hello'] }, labels: ['ACTED_IN'] };

Find node or relationship using a Sequence (note that the valid directions are ANY, INCOMING, OUTGOING)

const seq = Sequence.node(theMatrix, 'movies').relationship(rel_def, 'rel', INCOMING).node(actor, 'actors');
  .then(({ movies, actors }) => {
        // I am not sure this is the best way to return data, maybe return the row instean
  .catch(ex => {})

You can also use other conditions on the query

    .then(({ movies }) => {});


To find only one node

.findOne(Sequence.node({ id: 21 }, 'cuba'))
.then(({ cuba }) => Array.isArray(cuba)) // false


To create a new node

const Bill = {
    labels: ['Person'],
    born: 1986,
    name: 'Bill'

The Node Object

Each call to createNode, findOne or find return a node proxy around the original driver implementation https://neo4j.com/docs/api/javascript-driver/current/class/src/v1/graph-types.js~Node.html

The proxy has the following properties:

  • to access id: node.id
  • to access labels: node.labels
  • to access any other properties: node.property_name
  • to access the original object: node._target

Also all the value of type Integer are converted on access

The proxy also have a save function to update the node

const Bill = {
     labels: ['Person'],
     born: 1986,
     name: 'Bill'

     .then(bill => {
        bill.lastName = 'bob';
        return bill.save()      // Update the node in the DB
     .then(newBill => {
        console.log(newBill.lastName) // bob

Furthermore, the proxy has a "del()" method that enables you to delete the proxied node or relationship. Nodes also have a "addRelation(data, direction, label, other_node, properties = {})" method to add relationships:

const seq = Sequence.node(theMatrix, 'movies').relationship({labels: ['ACTED_IN'], 'rel', INCOMING).node(
        labels: ['Person'],

    .then(({ actors }) => {

        var actor1 = actors[0];
        var actor2 = actors[1];

        actor1.addRelation(OUTGOING, 'LOVES', actor2);
        actor1.addRelation(INCOMING, 'HATES', actor2);


The node object also has a getRelation(data, tag, direction, label, properties = {}) method which allows you to fetch relationships from an existing node: var seq = Sequence.node(theMatrix, 'movies').relationship({labels: ['ACTED_IN']}).node( { labels: ['Person'], }, 'actors' );

var rel_def = {
    roles: { $eq : ["Neo"] },

    .then(({ actors }) => {

        var actor1 = actors[0];

        actor1.getRelation('role', OUTGOING, 'ACTED_IN', rel_def)
           .then(({ role }) => {