ostrio:neo4jreactivity

v0.5.4Published 9 years ago

This package has not had recent updates. Please investigate it's current state before committing to using it in your project.

Neo4j DB reactive layer for Meteor

Neo4j reactivity creates mongodb layer between neo4j and your Meteor based application. All write requests is synchronized between all clients. Please see this package on atmospherejs.com .

Example App

The basic example is build on top of --example leaderboard - the Meteor Leaderboard Neo4j Example App

Description

Due to security lack we decide separate server side with queries, and client side with handlers via methods.

To create method use Meteor.neo4j.methods({'object of functions'}) with functions which returns query string (see example below).

To call and handle database answer use: Meteor.neo4j.call('methodName', {'A map of parameters for the Cypher query'}, function(error, data){...})

Install the driver
meteor add ostrio:neo4jreactivity
Known issues:
  • Error: Neo4jCacheCollection.upsert in v2.2.*: - You need to disable default authentication in Neo4j-2.2.*:
    • Open file /Your_Neo4j-2.2.0_install_path/conf/neo4j-server.properties
    • Change line: dbms.security.auth_enabled=true (to false)
Usage example:
In Server Methods
1#CoffeeScript
2Meteor.neo4j.methods 
3    getUsersFriends: () ->
4        return  'MATCH (a:User {_id: {userId}})-[relation:friends]->(b:User) ' +
5                'OPTIONAL MATCH (b:User)-[subrelation:friends]->() ' +
6                'RETURN relation, subrelation, b._id AS b_id, b'
In Helper
1#CoffeeScript
2Template.friendsNamesList.helpers
3    userFriends: () ->
4
5        Meteor.neo4j.call 'getUsersFriends', {userId: '12345'}, (error, data) ->
6            if error
7                 #handle error here
8                 throw new Meteor.error '500', 'Something goes wrong here', error.toString()
9            else
10                Session.set 'currenUserFriends', data
11
12        return Session.get 'currentUserFriens'
In Template:
1<template name="friendsNamesList">
2    <ul>
3        {{#each userFriends.b}}
4           <li>{{b.name}}</li>
5        {{/each}}
6    </ul>
7</template>
About security

By default query execution is allowed only on server, but for development purpose (or any other), you may enable it on client:

1#Write this line in /lib/ directory to execute this code on both client and server side
2Meteor.neo4j.allowClientQuery = true
3#Do not forget about minimum security, deny all write queries
4Meteor.neo4j.set.deny Meteor.neo4j.rules.write

To allow or deny actions use neo4j.set.allow(['array of strings']) and neo4j.set.deny(['array of strings'])

1#CoffeeScript
2Meteor.neo4j.set.allow ['create', 'Remove']
3Meteor.neo4j.set.deny ['SKIP', 'LIMIT']
4
5#OR to allow or deny all
6Meteor.neo4j.set.allow '*'
7Meteor.neo4j.set.deny '*'
8
9#To deny all write operators
10Meteor.neo4j.set.deny Meteor.neo4j.rules.write
11
12#default rules
13Meteor.neo4j.rules = 
14    allow: ['RETURN', 'MATCH', 'SKIP', 'LIMIT', 'OPTIONAL', 'ORDER BY', 'WITH', 'AS', 'WHERE', 'CONSTRAINT', 'UNWIND', 'DISTINCT', 'CASE', 'WHEN', 'THEN', 'ELSE', 'END', 'CREATE', 'UNIQUE', 'MERGE', 'SET', 'DELETE', 'REMOVE', 'FOREACH', 'ON', 'INDEX', 'USING', 'DROP']
15    deny: []
Execute query on client side:
1#Write this line in /lib/ directory to execute this code on both client and server side
2Meteor.neo4j.allowClientQuery = true
3
4#Client code
5getAllUsers = () ->
6    return Session.get('allUsers', Meteor.neo4j.query('MATCH (a:User) RETURN a'));

For more info see: neo4jdriver and node-neo4j

Code licensed under Apache v. 2.0: node-neo4j License


Testing & Dev usage
Local usage
  • Download (or clone) to local dir
  • Stop meteor if running
  • Run mrt link-package [*full path to folder with package*] in a project dir
  • Then run meteor add ostrio:neo4jreactivity
  • Run meteor in a project dir
  • From now any changes in ostrio:neo4jreactivity package folder will cause rebuilding of project app

Understanding the package

After installing ostrio:neo4jreactivity package - you will have next variables:

  • Meteor.Neo4j;
  • Meteor.N4JDB;
  • Meteor.neo4j;
var Neo4j;
1/* 
2 * Server only
3 * @class
4 * @name Neo4j
5 * @param url {string} - url to Neo4j database
6 * Note: It’s better to store url in environment 
7 * variable, 'NEO4J_URL' or 'GRAPHENEDB_URL' - 
8 * so it will be automatically picked up by our driver
9 * 
10 * @description Run it to create connection to database
11 */
12var N4JDB = new Neo4j();

Newly created object has next functions, you will use:

1/* @name query */
2Meteor.N4JDB.query('MATCH (n:User) RETURN n', null /* A map of parameters for the Cypher query */, function(err, data){
3    Session.set('allUsers', data);
4});
5
6/* @name listen */
7Meteor.N4JDB.listen(function(query, opts){
8    console.log('Incoming request to neo4j database detected!');
9});
var neo4j;
1/* Both (Client and Server)
2 * @object
3 * @name neo4j
4 * @description Application wide object neo4j
5 */
6Meteor.neo4j;
7Meteor.neo4j.allowClientQuery = true; /* Allow/deny client query executions */
8Meteor.neo4j.connectionURL = null; /* Set custom connection URL to Neo4j DB, Note: It’s better to store url in environment variable, 'NEO4J_URL' or 'GRAPHENEDB_URL' - so it will be automatically picked up by the driver */

neo4j object has multiple functions, you will use:

1/* @namespace neo4j.set
2 * @name allow
3 * @param rules {array} - Array of Cypher operators to be allowed in app
4 */
5Meteor.neo4j.set.allow(rules /* array of strings */);
6
7/* @namespace neo4j.set
8 * @name deny
9 * @param rules {array} - Array of Cypher operators to be forbidden in app
10 */
11Meteor.neo4j.set.deny(rules /* array of strings */);
12
13
14/*
15 * @function
16 * @namespace neo4j
17 * @name query
18 * @param query {string}      - Cypher query
19 * @param opts {object}       - A map of parameters for the Cypher query
20 * @param callback {function} - Callback function(error, data){...}. Where is data is [REACTIVE DATA SOURCE]
21 *                              So to get data for query like:
22 *                              'MATCH (a:User) RETURN a', you will need to: 
23 *                              data.a
24 * @param settings {object}   - {returnCursor: boolean} if set to true, returns Mongo\Cursor 
25 * @description Isomorphic Cypher query call
26 * @returns Mongo\Cursor or ReactiveVar [REACTIVE DATA SOURCE] 
27 *
28 * @note Please keep in mind what on client it returns ReactiveVar, but on server it returns just data, see difference in usage at example below
29 *
30 */
31allUsers = Meteor.neo4j.query('MATCH (users:User) RETURN users');
32var users = allUsers.get().users;
33
34/* or via callback, on callback there is no need to run `get()` method */
35var users;
36Meteor.neo4j.query('MATCH (users:User) RETURN users', null, function(error, data){
37    users = data.users;
38});
39
40
41/*
42 * Server only
43 * @name methods
44 * @param methods {object} - Object of methods, like: { methodName: function(){ return 'MATCH (a:User {name: {userName}}) RETURN a' } }
45 * @description Create server methods to send query to neo4j database
46 */
47Meteor.neo4j.methods({
48   'GetAllUsers': function(){
49      return 'MATCH (users:User) RETURN users';
50   }
51});
52
53
54/*
55 * Client only
56 * @name call
57 * @description Call for server method registered via neo4j.methods() method, 
58 *              returns error, data via callback.
59 */
60Meteor.neo4j.call('GetAllUsers', null, function(error, data){
61   Session.set('AllUsers', data.users);
62});
var N4JDB;
1/* 
2 * Server only
3 * @description Current GraphDatabase connection object, basically created from 'new Neo4j()''
4 */
5Meteor.N4JDB;
6
7
8/* You may run queries with no returns on server with it: */
9Meteor.N4JDB.query('CREATE (a:User {_id: ”123”})');
10
11
12/* To set listener: */
13Meteor.N4JDB.listen(function(query, opts){
14  console.log('Incoming query: ' + query, opts);
15});