Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 30 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,27 +30,36 @@ npm install redisgraph.js
# Example: Using the JavaScript Client

```javascript
const RedisGraph = require("redisgraph.js").RedisGraph;

let graph = new RedisGraph('social');
graph
.query("CREATE (:person{name:'roi',age:32})")
.then( () => {
return graph.query("CREATE (:person{name:'amit',age:30})");
})
.then( () => {
return graph.query("MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(b)")
})
.then( () => {
return graph.query("MATCH (a:person)-[:knows]->(:person) RETURN a")
})
.then( (res) => {
while(res.hasNext()){
let record = res.next();
console.log(record.getString('a.name'));
}
console.log(res.getStatistics().queryExecutionTime());
});
const RedisGraph = require("redisgraph.js").Graph;

let graph = new RedisGraph("social");

graph.query("CREATE (:person{name:'roi',age:32})").then(() => {
graph.query("CREATE (:person{name:'amit',age:30})").then(()=>{
graph.query("MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(b)").then(()=>{
graph.query("MATCH (a:person)-[:knows]->(:person) RETURN a.name").then(res=>{
while (res.hasNext()) {
let record = res.next();
console.log(record.get("a.name"));
}
console.log(res.getStatistics().queryExecutionTime());
graph.query("MATCH p = (a:person)-[:knows]->(:person) RETURN p").then(res=>{
while (res.hasNext()) {
let record = res.next();
// See path.js for more path API.
console.log(record.get("p").nodeCount);
graph.deleteGraph();
process.exit();
}
})
})
})
})
})
.catch(err => {
console.log(err);
});


```

Expand Down
42 changes: 22 additions & 20 deletions examples/redisGraphExample.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
const RedisGraph = require("redisgraph.js").RedisGraph;
const RedisGraph = require("redisgraph.js").Graph;

let graph = new RedisGraph("social");

graph
.query("CREATE (:person{name:'roi',age:32})")
.then(() => {
return graph.query("CREATE (:person{name:'amit',age:30})");
})
.then(() => {
return graph.query(
"MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(a)"
);
})
.then(() => {
return graph.query("MATCH (a:person)-[:knows]->(:person) RETURN a");
})
.then(res => {
while (res.hasNext()) {
let record = res.next();
console.log(record.getString("a.name"));
}
console.log(res.getStatistics().queryExecutionTime());
graph.query("CREATE (:person{name:'roi',age:32})").then(() => {
graph.query("CREATE (:person{name:'amit',age:30})").then(()=>{
graph.query("MATCH (a:person), (b:person) WHERE (a.name = 'roi' AND b.name='amit') CREATE (a)-[:knows]->(b)").then(()=>{
graph.query("MATCH (a:person)-[:knows]->(:person) RETURN a.name").then(res=>{
while (res.hasNext()) {
let record = res.next();
console.log(record.get("a.name"));
}
console.log(res.getStatistics().queryExecutionTime());
graph.query("MATCH p = (a:person)-[:knows]->(:person) RETURN p").then(res=>{
while (res.hasNext()) {
let record = res.next();
// See path.js for more path API.
console.log(record.get("p").nodeCount);
graph.deleteGraph();
process.exit();
}
})
})
})
})
})
.catch(err => {
console.log(err);
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"url": "git://github.com/redislabs/redisgraph.js.git"
},
"dependencies": {
"deep-equal": "^1.1.0",
"redis": "^2.8.0"
},
"devDependencies": {
Expand Down
1 change: 1 addition & 0 deletions src/edge.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"use strict";
/**
* An edge connecting two nodes.
*/
Expand Down
1 change: 1 addition & 0 deletions src/graph.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"use strict";
const redis = require("redis"),
util = require("util"),
ResultSet = require("./resultSet");
Expand Down
1 change: 1 addition & 0 deletions src/label.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"use strict";
/**
* Different Statistics labels
*/
Expand Down
1 change: 1 addition & 0 deletions src/node.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"use strict";
/**
* A node within the garph.
*/
Expand Down
46 changes: 46 additions & 0 deletions src/path.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"use strict";
class Path {
constructor(nodes, edges){
this.nodes = nodes;
this.edges = edges;
}

get Nodes(){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DvirDukhan capital letter?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

return this.nodes;
}

get Edges(){
return this.edges;
}

getNode(index){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should you use gettter/setter?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please elaborate

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is a property getter, so done, for every zero parametes function

return this.nodes[index];
}

getEdge(index){
return this.edges[index];
}

get firstNode(){
return this.nodes[0];
}

get lastNode(){
return this.nodes[this.nodes.length -1];
}

get nodeCount(){
return this.nodes.length;
}

get edgeCount(){
return this.edges.length;
}

toString() {
return JSON.stringify(this);
}

}

module.exports = Path;
1 change: 1 addition & 0 deletions src/record.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"use strict";
/**
* Hold a query record
*/
Expand Down
22 changes: 17 additions & 5 deletions src/resultSet.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
"use strict";
const Statistics = require("./statistics"),
Record = require("./record");
Node = require("./node");
Edge = require("./edge");
ReplyError = require("redis").ReplyError
Record = require("./record"),
Node = require("./node"),
Edge = require("./edge"),
Path = require("./path"),
ReplyError = require("redis").ReplyError;

const ResultSetColumnTypes = {
COLUMN_UNKNOWN: 0,
Expand All @@ -20,7 +22,8 @@ const ResultSetValueTypes = {
VALUE_DOUBLE: 5,
VALUE_ARRAY: 6,
VALUE_EDGE: 7,
VALUE_NODE: 8
VALUE_NODE: 8,
VALUE_PATH: 9
}

/**
Expand Down Expand Up @@ -190,6 +193,12 @@ class ResultSet {
return rawArray;
}

async parsePath(rawPath) {
let nodes = await this.parseScalar(rawPath[0]);
let edges = await this.parseScalar(rawPath[1]);
return new Path(nodes, edges);
}

async parseScalar(cell) {
let scalar_type = cell[0];
let value = cell[1];
Expand Down Expand Up @@ -224,6 +233,9 @@ class ResultSet {
case ResultSetValueTypes.VALUE_EDGE:
scalar = await this.parseEdge(value);
break;
case ResultSetValueTypes.VALUE_PATH:
scalar = await this.parsePath(value);
break;
case ResultSetValueTypes.VALUE_UNKNOWN:
console.log("Unknown scalar type\n");
break;
Expand Down
1 change: 1 addition & 0 deletions src/statistics.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"use strict";
const Label = require("./label");

class Statistics {
Expand Down
36 changes: 36 additions & 0 deletions test/pathBuilder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"use strict";
const Node = require("../src/node"),
Edge = require("../src/edge"),
Path = require("../src/path");

class PathBuilder {
constructor(nodeCount){
this.nodes = new Array();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

     this.nodes = []; 

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

this.edges = new Array();
this.currentAppendClass = Node;
}

append(obj){
if(! obj instanceof this.currentAppendClass) throw "Error in path build insertion order and types."
if(obj instanceof Node) return this._appendNode(obj);
else return this._appendEdge(obj);
}

build(){
return new Path(this.nodes, this.edges);
}

_appendNode(node){
this.nodes.push(node);
this.currentAppendClass = Edge;
return this;
}

_appendEdge(edge){
this.edges.push(edge);
this.currentAppendClass = Node;
return this;
}
}

module.exports = PathBuilder;
72 changes: 71 additions & 1 deletion test/redisGraphAPITest.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
"use strict";
const assert = require("assert"),
redis = require("redis"),
Label = require("../src/label"),
RedisGraph = require("../src/graph");
RedisGraph = require("../src/graph"),
Node = require("../src/node"),
Edge = require("../src/edge"),
Path = require("../src/path"),
PathBuilder = require("./pathBuilder"),
deepEqual = require('deep-equal');

describe('RedisGraphAPI Test', function () {
const api = new RedisGraph("social");
Expand Down Expand Up @@ -288,4 +294,68 @@ describe('RedisGraphAPI Test', function () {
})
})

it('unitTestPath', ()=>{
let node0 = new Node("L1", {});
node0.setId(0);
let node1 = new Node("L1", {});
node1.setId(1);

let edge01 = new Edge(0, "R1", 1, {});
edge01.setId(0);

let path01 = new PathBuilder().append(node0).append(edge01).append(node1).build();

assert.equal(1, path01.edgeCount);
assert.equal(2, path01.nodeCount);
assert.deepEqual(node0, path01.firstNode);
assert.deepEqual(node0, path01.getNode(0));
assert.deepEqual(node1, path01.lastNode);
assert.deepEqual(node1, path01.getNode(1));
assert.deepEqual(edge01, path01.getEdge(0));
assert.deepEqual([node0, node1], path01.nodes);
assert.deepEqual([edge01], path01.edges);

})

it('testPath', (done)=>{
api.query("CREATE (:L1)-[:R1]->(:L1)-[:R1]->(:L1)").then(response => {
api.query("MATCH p = (:L1)-[:R1*]->(:L1) RETURN p").then(response =>{
let node0 = new Node("L1", {});
node0.setId(0);
let node1 = new Node("L1", {});
node1.setId(1);
let node2 = new Node("L1", {});
node2.setId(2);
let edge01 = new Edge(0, "R1", 1, {});
edge01.setId(0);
let edge12 = new Edge(1, "R1", 2, {});
edge12.setId(1);

let path01 = new PathBuilder().append(node0).append(edge01).append(node1).build();
let path12 = new PathBuilder().append(node1).append(edge12).append(node2).build();
let path02 = new PathBuilder().append(node0).append(edge01).append(node1).append(edge12).append(node2).build();

let paths = new Set([path01, path12, path02]);
while(response.hasNext()){
let p = response.next().get("p");
let pInPaths = false;
let path = null;
let pathsIterator = paths.values();
for( pathsIterator; path = pathsIterator.next().value;){
if(deepEqual(p ,path)){
pInPaths = true;
break;
}
}
assert(pInPaths);
paths.delete(path);
}
assert.equal(0, paths.size);
done();
})
}).catch(error => {
console.log(error);
})
})

});