bretcope / neo4j-js Goto Github PK
View Code? Open in Web Editor NEWA Node.js (pure JavaScript) client library for accessing neo4j databases with batch support.
License: MIT License
A Node.js (pure JavaScript) client library for accessing neo4j databases with batch support.
License: MIT License
Implement wrappers for the Configurable Automatic Indexing API.
http://docs.neo4j.org/chunked/stable/rest-api-configurable-auto-indexes.html
I have been using your module.
One modification is needed
Neo4jApi.js
132 line
_endpoints[i] = Url.parse(obj[i]);
-->
_endpoints[i] = Url.parse(obj[i].toString());
Implement wrappers for the REST API enpoints exposing the built-in graph algorithms.
http://docs.neo4j.org/chunked/stable/rest-api-graph-algos.html
Implement wrappers for the Gremlin API.
http://docs.neo4j.org/chunked/stable/gremlin-plugin.html
This issue is not assigned to a milestone because its priority is uncertain.
How do we create unique node? and I also want unique index on some of my node property. (eg. If my node is a type of user, then it should be unique username, email and mobileno.)
thanks
Hello,
Perhaps you can shed some light on my problem. I have the following code :
var neo = require('neo4j-js');
Promise.promisifyAll(neo);
// Promises Connect version
neo.connectAsync('http://localhost:7474/db/data/')
.spread(function(err, graph) {
Promise.promisifyAll(graph);
var queryText = [
'MATCH n WHERE NOT has(n.admin)',
'RETURN distinct labels(n) as l'
].join('\n');
graph.queryAsync(queryText)
.then(function(result) {
console.log(result);
});
})
.catch(function (e) {
console.error('Connection issue encountered');
throw e;
});
// Non-promise Connect version
neo.connect('http://localhost:7474/db/data/', function(err, graph) {
Promise.promisifyAll(graph);
var queryText = [
'MATCH n WHERE NOT has(n.admin)',
'RETURN distinct labels(n) as l'
].join('\n');
graph.queryAsync(queryText)
.then(function(result) {
console.log(result);
});
});
The first version sets graph to be undefined :
Connection issue encountered
Possibly unhandled TypeError: the target of promisifyAll must be an object or a function
The second version returns perfectly and shows the correct JSON response.
I can't work out why the call to promisifyAll seems to cause this, can you suggest anything ?
Does the library support labels introduced in neo4j v2.0 ? If yes, can you provide an example please?
Hello. First off thanks for writing this library!
I was wondering, how do you update a node without using cypher? It doesn't seem like there is an API call for something like that.
Thanks,
for (var i in requests)
{
requests[obj[i].id].callback(null, obj[i].body);
}
where i should be index of requests but its coming as string due to unknown reason. I inspect requests object too, which have array of three objects, but value of i assigned as "getTitle" which I have not set to any where in my app. hence code was breaking while calling obj[i].id.
to over come I changed for loop implementation to for(var i=0;i<requests.length;i++){..} and thats it. I still didn't find the possible cause of that error.
@bretcope Are the following queries possible when using this node module?
var query = 'MATCH user:{userLabel} {id: {uid}} RETURN user'
var query = 'MATCH user:{userLabel} {id: {uid}}-[rel:{relationshipLabel} {is_old: true}]-(system:System {id: {sysId}}) RETURN user, system'
Hi,
There seems to have a bug on line 88 of Graph.js as in case when you send a REST query without any corresponding query parameters it will fail. It seems that args-object doesn't have any callback function to reach out in order to handle the error condition.
This is when I change it to log out the error object:
args.callback(error);
^
TypeError: Object Error: Invalid Arguments has no method 'callback'
debug: --------------------------------------------------------
{ [Error: You have to provide the 'query' parameter.]
code: 400,
innerError:
{ message: 'You have to provide the 'query' parameter.',
exception: 'BadInputException',
fullname: 'org.neo4j.server.rest.repr.BadInputException',
stacktrace:
[ 'org.neo4j.server.rest.web.CypherService.cypher(CypherService.java:76)',
'java.lang.reflect.Method.invoke(Method.java:606)',
'org.neo4j.server.rest.transactional.TransactionalRequestDispatcher.dispatch(TransactionalRequestDispatcher.java:139)',
'org.neo4j.server.rest.security.SecurityFilter.doFilter(SecurityFilter.java:112)',
'java.lang.Thread.run(Thread.java:745)' ] },
exception: 'BadInputException',
fullname: 'org.neo4j.server.rest.repr.BadInputException' }
I'm using neo4j-js for high volume data insertion and I feel the need to have a callback after a complete and successful batch execution, it's possible to consider this feature in the next release ?
Thank you in advance!
I have stored my data in neo4j as follows.
graph.createNode({ UserID: 599, UserName: someName, EMail: [email protected], MobileNo : "+9XXXXXXXXX" }, function (err, node) {
console.log(err ? err : node);
});
Now I want that node by UserID (e.g. 599) or may be I want that by UserName or EMail.
How can I do?
Thanks
query
START section=node(7,5,3)
Optional Match (attachment)-[a:Attached]->(section)
return section,attachment
results
[ { section: { id: '7', data: [Object] }, attachment: null },
{ section: { id: '5', data: [Object] },
attachment:
{ labels: 'http://localhost:7474/db/data/node/6/labels',
outgoing_relationships: 'http://localhost:7474/db/data/node/6/relationships/out',
data: [Object],
traverse: 'http://localhost:7474/db/data/node/6/traverse/{returnType}',
all_typed_relationships: 'http://localhost:7474/db/data/node/6/relationships/all/{-list|&|types}',
self: 'http://localhost:7474/db/data/node/6',
property: 'http://localhost:7474/db/data/node/6/properties/{key}',
outgoing_typed_relationships: 'http://localhost:7474/db/data/node/6/relationships/out/{-list|&|types}',
properties: 'http://localhost:7474/db/data/node/6/properties',
incoming_relationships: 'http://localhost:7474/db/data/node/6/relationships/in',
extensions: {},
create_relationship: 'http://localhost:7474/db/data/node/6/relationships',
paged_traverse: 'http://localhost:7474/db/data/node/6/paged/traverse/{returnType}{?pageSize,leaseTime}',
all_relationships: 'http://localhost:7474/db/data/node/6/relationships/all',
incoming_typed_relationships: 'http://localhost:7474/db/data/node/6/relationships/in/{-list|&|types}' } },
{ section: { id: '3', data: [Object] },
attachment:
{ labels: 'http://localhost:7474/db/data/node/4/labels',
outgoing_relationships: 'http://localhost:7474/db/data/node/4/relationships/out',
data: [Object],
traverse: 'http://localhost:7474/db/data/node/4/traverse/{returnType}',
all_typed_relationships: 'http://localhost:7474/db/data/node/4/relationships/all/{-list|&|types}',
self: 'http://localhost:7474/db/data/node/4',
property: 'http://localhost:7474/db/data/node/4/properties/{key}',
outgoing_typed_relationships: 'http://localhost:7474/db/data/node/4/relationships/out/{-list|&|types}',
properties: 'http://localhost:7474/db/data/node/4/properties',
incoming_relationships: 'http://localhost:7474/db/data/node/4/relationships/in',
extensions: {},
create_relationship: 'http://localhost:7474/db/data/node/4/relationships',
paged_traverse: 'http://localhost:7474/db/data/node/4/paged/traverse/{returnType}{?pageSize,leaseTime}',
all_relationships: 'http://localhost:7474/db/data/node/4/relationships/all',
incoming_typed_relationships: 'http://localhost:7474/db/data/node/4/relationships/in/{-list|&|types}' } } ]
any idea what would cause this
I try to load the root node, like so:
graph.getNode(0, ...)
graph.getNode([0], ...)
and it throws the following exception:
SyntaxError: Unexpected token <
at Object.parse (native)
at IncomingMessage.<anonymous> (/Users/simon/Code/soho/node_modules/neo4j-js/lib/Neo4jApi.js:241:18)
at IncomingMessage.EventEmitter.emit (events.js:117:20)
at _stream_readable.js:912:16
at process._tickCallback (node.js:415:13)
Upon further investigation, I found that library is generating the incorrect endpoint URL: /db/data/node
, when it should be /db/data/node/0
.
Implement wrappers for the Unique Indexes API.
http://docs.neo4j.org/chunked/stable/rest-api-unique-indexes.html
I'm receiving the following error when trying to do a batch query.
/Users/ro/Documents/neo4j-test/node_modules/neo4j-js/lib/Neo4jApi.js:319
requests[obj[i].id].callback(null, obj[i].body);
^
TypeError: Cannot read property 'id' of undefined
at /Users/ro/Documents/neo4j-test/node_modules/neo4j-js/lib/Neo4jApi.js:319:21
at IncomingMessage.<anonymous> (/Users/ro/Documents/neo4j-test/node_modules/neo4j-js/lib/Neo4jApi.js:262:6)
at IncomingMessage.EventEmitter.emit (events.js:117:20)
at _stream_readable.js:920:16
at process._tickCallback (node.js:415:13)
I'm batching together tens of thousands of requests but when I dig deeper, it appears that the runBatch()
function is only showing 751 requests.
Suppose this data structure and query: http://console.neo4j.org/?id=5v6mrv
If the query result contains a null in a certain column, but a non-null in the same column, things can be messed up based on null came first or not (due to dynamic constructor determination run only on first row).
Below are a few test cases covering some possibilities (change the url and run with nodeunit require('nodeunit').reporters['default'].run(['neo4j.bugs.js'])
). See test comments for results and stack traces.
var neo4j = require('neo4j-js'); // https://github.com/bretcope/neo4j-js/blob/master/docs/Documentation.md
exports.testBugs = {
setUp: function (callback) {
var test = this;
this.callback = function(test) {
return function(err, results) {
test.ifError(err);
test.done();
}
}
neo4j.connect('http://username:password@yourhost:12345/db/data/', function (err, graph) {
if (err) { throw err; }
console.log('Connected to ' + graph.version);
test.graph = graph;
callback();
});
},
beforeClass: function(test) {
test.ok(this.graph, "No graph");
this.graph.query('MATCH (x:X) OPTIONAL MATCH (x)-[r]-(y:Y) DELETE x, r, y', this.callback(test));
},
testInit: function(test) {
this.graph.query('CREATE (_0:X {name:"a"}), (_1:X {name:"b"}), (_2:Y {name:"c"}), _0-[:REF]->_2', this.callback(test));
},
testWorks: function(test) { // both x and y are non-nulls in all rows
// result row1: a, c;
this.graph.query('MATCH (x:X) MATCH (x)-[:REF]->y RETURN x, y',
function check(err, results) {
test.ifError(err);
console.log(JSON.stringify(results, true, ' '));
test.equal(results.length, 1);
test.equal(results[0].x.data.name, 'a');
test.equal(results[0].y.data.name, 'c');
test.done();
}
);
},
testBug1a: function(test) { // null first
// result row1: b and null; row2: a and c
this.graph.query('MATCH (x:X) OPTIONAL MATCH (x)-[:REF]->y RETURN x, y ORDER BY x.name DESC',
function check(err, results) {
test.ifError(err);
console.log(JSON.stringify(results, true, ' '));
test.equal(results.length, 2);
test.equal(results[0].x.data.name, 'b');
test.equal(results[0].y, null);
test.equal(results[1].x.data.name, 'a');
test.equal(results[1].y.data.name, 'c');
test.ok(typeof results[1].x.self === 'undefined');
test.ok(typeof results[1].y.self === 'string'); // should be undefined too
test.done();
}
);
},
testBug1b: function(test) { // null first as empty object
// result row1: b and {}; row2: a and c
this.graph.query('MATCH (x:X) OPTIONAL MATCH (x)-[:REF]->y RETURN x, COALESCE(y, {}) as y ORDER BY x.name DESC',
function check(err, results) {
test.ifError(err);
console.log(JSON.stringify(results, true, ' '));
test.equal(results.length, 2);
test.equal(results[0].x.data.name, 'b');
test.deepEqual(results[0].y, {});
test.equal(results[1].x.data.name, 'a');
test.equal(results[1].y.data.name, 'c');
test.ok(typeof results[1].x.self === 'undefined');
test.ok(typeof results[1].y.self === 'string'); // should be undefined too
test.done();
}
);
},
/*
node_modules\neo4j-js\lib\Base.js:44
this.id = neo4j.Utils.parseId(obj.self);
^
TypeError: Cannot read property 'self' of null
at Node.Base (node_modules\neo4j-js\lib\Base.js:44:36)
at new Node (node_modules\neo4j-js\lib\Node.js:42:14)
at query (node_modules\neo4j-js\lib\Graph.js:129:76)
at IncomingMessage.module.exports.connect.Request.createCallback (node_modules\neo4j-js\lib\Neo4jApi.js:262:6)
at IncomingMessage.EventEmitter.emit (events.js:126:20)
at IncomingMessage._emitEnd (http.js:366:10)
at HTTPParser.parserOnMessageComplete [as onMessageComplete] (http.js:149:23)
at Socket.socketOnData [as ondata] (http.js:1367:20)
at TCP.onread (net.js:403:27)
*/
testBug2a: function(test) { // null not first
// result row1: a, c; row2: b, null
this.graph.query('MATCH (x:X) OPTIONAL MATCH (x)-[:REF]->y RETURN x, y ORDER BY x.name ASC',
function check(err, results) {
// doesn't get here, throws on a different "thread"
test.ifError(err);
console.log(JSON.stringify(results, true, ' '));
test.done();
}
);
},
/*
node_modules\neo4j-js\lib\Neo4jUtils.js:129
return _idRegex.exec(url)[0];
^
TypeError: Cannot read property '0' of null
at module.exports.parseId (node_modules\neo4j-js\lib\Neo4jUtils.js:129:28)
at Node.Base (node_modules\neo4j-js\lib\Base.js:44:25)
at new Node (node_modules\neo4j-js\lib\Node.js:42:14)
at query (node_modules\neo4j-js\lib\Graph.js:129:76)
at IncomingMessage.module.exports.connect.Request.createCallback (node_modules\neo4j-js\lib\Neo4jApi.js:262:6)
at IncomingMessage.EventEmitter.emit (events.js:126:20)
at IncomingMessage._emitEnd (http.js:366:10)
at HTTPParser.parserOnMessageComplete [as onMessageComplete] (http.js:149:23)
at Socket.socketOnData [as ondata] (http.js:1367:20)
at TCP.onread (net.js:403:27)
*/
testBug2b: function(test) { // null not first as empty object
// result row1: a, c; row2: b, {}
this.graph.query('MATCH (x:X) OPTIONAL MATCH (x)-[:REF]->y RETURN x, COALESCE(y, {}) as y ORDER BY x.name ASC',
function check(err, results) {
// doesn't get here, throws on a different "thread"
test.ifError(err);
console.log(JSON.stringify(results, true, ' '));
test.done();
}
);
},
afterClass: function(test) {
test.ok(this.graph, "No graph");
this.graph.query('MATCH (x:X) OPTIONAL MATCH (x)-[r]-(y:Y) DELETE x, r, y', this.callback(test));
}
};
Implement wrappers for the Traversals API.
http://docs.neo4j.org/chunked/stable/rest-api-traverse.html
This issue is not attached to a milestone because its priority is uncertain.
I think its better for readability as refreshProperties sounds like reset where as its just getting the properties (isn't it ? )
Currently when nodes are retunred from a cypher query they are in this format:
[ { attachment: { id: '21', data: [Object] } },
{ attachment: { id: '20', data: [Object] } } ]
In this example the attachments have different labels
I propose an addition where the return would be:
[ { attachment: { id: '21' ,labels:['document'], data: [Object] } },
{ attachment: { id: '20', ,labels: ['link','label1'] ,data:[Object} } ]
I would make the changes in Graph.query(query,callback), while the result is being populated by adding a call to the following neo4j rest service
http://localhost:7474/db/data/node/{id}/labels.
I understand this may increase the overhead affecting performance, perhaps we could add a optional parameter "IncludeLabes"?
Hi Bret,
nice work you've done here.
Besides the readme do you have any blog posts or screencasts of the library that we could link to too?
A sample app, e.g. a small express webapp that uses neo4j-js and can directly deployed to heroku would be awesome. Perhaps throw in a little viz :)
I also wanted to ask if you could support the transactional http endpoint, b/c that one is to be the future, not only more compact but also transactional across requests, is streaming by default (great for node.js) and handles errors more consistently.
Do you plan to continue development on neo4j-js ?
Thanks Michael
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.