Decypher
decypher is a node.js library packing a handful of utilities to deal with cypher queries.
It includes the following:
Installation
You can install decypher from npm likewise:
npm install decypher
or from github if you need the latest development version:
npm install git+https://github.com/Yomguithereal/decypher.git
Query loader
Query files
Write one or more cypher queries per file:
File containing a single query
// Any comments...
MATCH (n)-[r]-(t)
RETURN n,r,t LIMIT 100;
File containing multiple named queries
// name: first
// Retrieve book nodes
MATCH (b:Book)
RETURN b;
// name: second
// Retrieve vocabulary nodes
MATCH (v:Vocabulary)
RETURN v;
Decyphering
Just require decypher and use it to load your queries:
var decypher = require('decypher');
decypher('./single-query.cypher');
>>> 'MATCH (n)-[r]-(t)\nRETURN n,r,t LIMIT 100;'
decypher('./multiple-queries.cypher');
>>> {
first: 'MATCH (b:Book)\nRETURN b;',
second: 'MATCH (v:Vocabulary)\nRETURN v;'
}
decypher({
single: './single-query.cypher',
multiple: './multiple-queries.cypher'
});
>>> {
single: 'MATCH (n)-[r]-(t)\nRETURN n,r,t LIMIT 100;',
multiple: {
first: 'MATCH (b:Book)\nRETURN b;',
second: 'MATCH (v:Vocabulary)\nRETURN v;'
}
}
decypher('./folder');
>>> {
single: 'MATCH (n)-[r]-(t)\nRETURN n,r,t LIMIT 100;',
multiple: {
first: 'MATCH (b:Book)\nRETURN b;',
second: 'MATCH (v:Vocabulary)\nRETURN v;'
}
}
decypher('./path-to-queries-folder', 'cql');
Now that if what you want is only to parse cypher strings because you retrieved the files on your, own, you can alternatively use decypher.parse
.
Query builder
Note that this query builder is widely inspired by the query-builder package by @shesek but fixed and updated to support cypher's latest evolutions.
The result object of the builder is also made to match @thingdom's node-neo4j specifications for the db.cypher
method.
var Query = require('decypher').Query;
var cypher = new Query()
.match('MATCH (n:Node)')
.where('n.title = {title}', {title: 'The best title'})
.return('n');
cypher.compile();
cypher.toString();
>>> `MATCH (n:Node)
WHERE n.title = {title}
RETURN n;`
cypher.params();
>>> {
title: 'The best title'
}
cypher.statements();
>>> [
'MATCH (n:Node)',
'WHERE n.title = {title}',
'RETURN n'
]
var {query, params, statements} = cypher.build();
cypher.orderBy('n.title');
cypher.params({whatever: 'is needed'});
cypher.param('whatever', 'is needed');
cypher.create(['(a:Actor)', '(m:Movie)']);
>>> 'CREATE (a:Actor), (m:Movie)'
cypher.add('anything you want');
cypher.add('with {param}', {param: 'heart'});
var cypher = new Query(),
start = cypher.segment(),
end = cypher.segment();
end.return('a');
start.match('(a:Actor)');
cypher.compile();
>>> `MATCH (a:Actor)
RETURN a;`
Expression builder
The expression builder lets you build where
expression easily:
var Expression = require('decypher').Expression;
var expr = new Expression('a = b');
expr.and('c = d');
expr.compile();
expr.toString();
>>> 'a = b AND c = d'
var expr = new Expression('a = b');
expr
.or(Expression('c = d').and('e = f'));
expr.compile();
>>> 'a = b OR (c = d AND e = f)'
expr.isEmpty();
>>> false
Helpers
Escaping identifiers
var helpers = require('decypher').helpers;
helpers.escapeIdentifier('Complex `Identifier`');
>>> '`Complex ``Identifier```'
Escaping literal maps
var helpers = require('decypher').helpers;
helpers.escapeLiteralMap({
hello: 'world',
'complex key': 3
});
>>> '{hello: "world", `complex key`: 3}'
helpers.escapeLiteralMap({
name: 'name',
number: 2
}, ['name']);
>>> '{name: {name}, number: 2}'
Building node patterns
var helpers = require('decypher').helpers;
helpers.nodePattern();
>>> '()'
helpers.nodePattern('n');
>>> '(n)'
helpers.nodePattern({
identifier: 'n',
label: 'Node'
});
>>> '(n:Node)'
helpers.nodePattern({
label: 'Node',
data: {title: 'Hello'}
});
>>> '(n:Node {title: "Hello"})'
helpers.nodePattern({
identifier: 'n',
data: 'paramName'
});
>>> '(n {paramName})'
helpers.nodePattern({
label: 'Chapter',
data: {title: 'title'},
paramKeys: ['title']
});
>>> '(:Chapter {title: {title}})'
Building relationship patterns
var helpers = require('decypher').helpers;
helpers.relationshipPattern();
>>> '--'
helpers.relationshipPattern('r');
>>> '-[r]-'
helpers.relationshipPattern({
direction: 'out',
identifier: 'r',
predicate: 'KNOWS'
});
>>> '-[r:KNOWS]->'
helpers.relationshipPattern({
direction: 'in',
predicate: ['PLAYS_IN', 'KNOWS']
});
>>> '<-[:PLAYS_IN|:KNOWS]-'
helpers.relationshipPattern({
direction: 'in',
identifier: 'r',
data: 'paramName'
});
>>> '<-[r {paramName}]-'
helpers.relationshipPattern({
predicate: 'KNOWS',
data: {since: 1975}
});
>>> '-[:KNOWS {since: 1975}]-'
helpers.relationshipPattern({
direction: 'out',
predicate: 'PLAYED_IN',
source: 'a',
target: {
identifier: 'm',
label: 'Movie'
}
});
>>> '(a)-[:PLAYED_IN]->(m:Movie)'
Building search patterns
Note that it will escape for query for regular expression use through the escape-regexp
module.
var helpers = require('decypher').helpers;
helpers.searchPattern('john');
>>> '(?ius).*john.*'
helpers.searchPattern('john', {flags: 'im'});
>>> '(?im).*john.*'
helpers.searchPattern('john', {flags: null, partial: false});
>>> 'john'
Contribution
Contributions are of course more than welcome. Be sure to add and pass any relevant unit tests before submitting any code.
git clone git@github.com:Yomguithereal/decypher.git
cd decypher
npm install
npm test
Roadmap
License
MIT