Fluent Cypher
This package allows you to build any cypher query you like and get both the query string and the parameters as an object to be used with the official neo4j driver.
If you want to be able to connect seamlessy to your Neo4j instance have a look at fluent-neo4j otherwise you can always use this package with your own driver/connector.
What is Cypher
This guide explains the basic concepts of Cypher, Neo4j’s query language.
Following the official documentation it is always better to avoid literals so everything is treated as a parameter.
Table of Contents
Usage
const CypherQuery = require('fluent-cypher');
import CypherQuery from 'fluent-cypher'
var query = new CypherQuery();
query.match({$: 'node'}, ['code', {type: 'KNOWS', direction: 'left'}, {}])
.where({$: 'node', value: {'<=': 25}}, 'OR', {$: 'node', value: 28})
.return({$: 'node', as: 'myValue')
.orderBy('myValue')
.limit(5)
constuctor([config])
onCreateSetTimestamp | Boolean | timestamps will be added for you like node.createdAt = timestamp() |
onUpdateSetTimestamp | Boolean | timestamps will be added for you like node.updatedAt = timestamp() |
userId | String | Property will be set like node.createdBy = {userId} and node.updatedBy = {userId} |
defaultNodeProps | Object | default props for every node |
forcetNodeProps | Object | force props for every node |
defaultRelProps | Object | default props for every relationship |
forcetRelProps | Object | force props for every relationship |
Building the query
.create(Pattern[, Pattern])
See Pattern for accepted arguments
query.create("(node)", "()->[rel]->()")
query.create({$: 'node1', prop: false}, {$: 'node2', val: 12})
query.create([{$: 'parent'}, {type: 'has'}, {$: 'child'}])
.match(Pattern[, Pattern])
See Pattern for accepted arguments
query.match("(node)")
query.match("(node)", "()->[rel]->()")
query.match({$: 'node1', prop: false}, {$: 'node2', val: 12})
query.match([{$: 'parent'}, {type: 'has'}, {$: 'child'}])
.optionalMatch(Pattern[, Pattern])
See Pattern for accepted arguments
query.optionalMatch("(node:Stuff)")
.where(WhereItem[, WhereItem])
query.where({$: 'user', fullName: {'=~': `(?i).*tom.*`}})
.merge(Pattern[, Pattern])
See Pattern for accepted arguments
query.merge("(node)")
query.merge("(node)", "()->[rel:`type`]->()")
.set(PropItem[, PropItem])
query.set('friend.rating = 5')
query.set({
$: 'friend',
labels: ['lol', 'lel'],
wow: '$rating'
})
.onCreateSet(PropItem[, PropItem])
query.onCreateSet('friend.rating = 5')
.onMatchSet(PropItem[, PropItem])
query.onCreateSet('friend.rating = 5')
.remove(PropItem[, PropItem])
query.remove({
$: 'p',
prop: 't',
props: ['lel', 'lol'],
label: 'one',
labels: ['may', 'april']
})
.delete(DeleteItem[, DeleteItem])
query
.match({$: 'lonely'})
.where('NOT', ['lonely', {type: 'has'}, {label: 'Friend'}])
.delete({$: 'lonely'})
.detachDelete(DeleteItem[, DeleteItem])
query
.match(['me', ':knows', {$: 'friend'})
.detachDelete('friend')
.return(ReturnItem[, ReturnItem])
query.return('*')
query.return('node')
query.return('node.prop')
query.return({$: 'node', prop: 'p', as: 'that'})
.returnDistinct(ReturnItem[, ReturnItem])
query.returnDistinct('*')
.limit(Integer)
query.limit(1)
.skip(Integer)
query.skip(1)
.orderBy(Integer)
query.orderBy({$: 'node', key: 'ASC'})
.unwind(UnwindItem)
query.unwind(['[1,2,3] as number')
query.unwind({$: [1,2,3], as: 'number'})
query.unwind({$: 'collection', as: 'list'})
query.unwind({$: '$param', as: 'entry'})
.with(AliasedItem[, AliasedItem])
query.with('this as that', {$: 'node', as: 'something'})
.union()
query.union()
.unionAll()
query.unionAll()
.loadCsv(url, options)
q.loadCsv('https://neo4j.com/docs/cypher-refcard/3.2/csv/artists.csv', {as: 'row', withHeaders: false})
.call(string)
q.call('dbms.procedures()')
.yield(string)
q.yield('name, signature')
Argument Types
Pattern
As String see Cypher
As Object see Node
As Array see Path
Cypher
String only
This is not manipulated at all and gets inserted in the context as is
'node'
'rel:type'
'CASE WHEN 1=1 THEN this ELSE that END as what'
Node
As String
see Cypher
As Object
$ | no | String | Variable name for node (must be valid variable name) |
label | no | String | Label for node |
labels | no | Array | Label for node |
...rest | no | String | Arrray |
{
$: 'node',
label: 'Cat',
labels: ['Animal', 'Living'],
this: 'that',
something: ['li', 'la']
}
Rel
As String
Interpreted as Cypher
As Object
Props
$ | no | String | Variable name for rel (must be valid variable name) |
type | yes (in merge) | String | Type of rel |
depth | no | `Integer | String` |
direction | no | String | Eiter left or right (default) or both |
...rest | no | `String | Arrray` |
| Example | | | |
{
$: 'rel',
type: 'Follows',
depth: '..5',
direction: 'both',
something: ['amigo']
}
Path
As Array
If the number of elements is even, the first Object is used for Path options
Props
$ | no | String | Variable name for path (must be valid variable name) |
shotestPath | no | Bool | Whether to use the shortestPath or not |
Example
[
{ $: 'myPath', shotestPath: true },
{ $: 'start' },
{},
'final'
]
.log()
As query.queryString is a parametrised string you may want to print a string that you can copy and paste in the browser console.
query
.match('(node)')
.log()
.match('()-[rel]->()')
.log()
Test
Tests are written in ava, run the following command
npm t