@v-doc/neorm

2.0.8 • Public • Published

NEORM

Description

A very simple neo4j javascript orm

Installation

npm install -S @jekel18/neorm

Import

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

Local build and test

npm run transpile
npm start

Usage

Sequence

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

MATCH (n:MOVIE) RETURN n

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

##Graph

The Graph object is used to interact with the database.

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

####find 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');
 
Graph
  .find(seq)
  .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

Graph
    .find(seq)
    .limit(3)
    .skip(2)
    .sort('actors.name')
    .then(({ movies }) => {});

###findOne To find only one node

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

###createNode To create a new node

const Bill = {
    labels: ['Person'],
    born: 1986,
    name: 'Bill'
};
 
Graph.createNode(Bill)
 .then(console.log);

##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'
};

Graph.createNode(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'],
    },
    'actors'
);

Graph
    .find(seq)
    .then(({ actors }) => {

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

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

        console.log('done');
    });

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"] },
};

Graph
    .find(seq)
    .then(({ actors }) => {

        var actor1 = actors[0];

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

Readme

Keywords

none

Package Sidebar

Install

npm i @v-doc/neorm

Weekly Downloads

10

Version

2.0.8

License

ISC

Unpacked Size

118 kB

Total Files

51

Last publish

Collaborators

  • blen2r
  • jekel18