Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Node.traverse() to allow custom graph traversals. #103

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
43 changes: 43 additions & 0 deletions lib/Node._coffee
Original file line number Diff line number Diff line change
Expand Up @@ -502,3 +502,46 @@ module.exports = class Node extends PropertyContainer

catch error
throw adjustError error

traverse: (returnType, options={}, _) ->
try
type = encodeURIComponent returnType
traverseURL = @_data['traverse']?.replace '{returnType}', type

if not traverseURL
throw new Error 'Traverse not available.'

res = @_request.post
url: traverseURL
json: options
, _

if res.statusCode isnt status.OK
throw new Error "Unrecognized response code: #{res.statusCode}"

data = res.body

switch type
when 'node'
return data.map (data) => new Node @db, data
when 'relationship'
return data.map (data) =>
if @self is data.start
new Relationship @db, data, this, null
else
new Relationship @db, data, null, this
when 'path'
start = new Node this, {self: data.start}
end = new Node this, {self: data.end}
length = data.length
nodes = data.nodes.map (url) =>
new Node this, {self: url}
relationships = data.relationships.map (url) =>
new Relationship this, {self: url, type}
return new Path start, end, length, nodes, relationships
else
return null;

catch error
throw adjustError error

75 changes: 75 additions & 0 deletions test/traverse._coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
{expect} = require 'chai'
flows = require 'streamline/lib/util/flows'
neo4j = require '..'

db = new neo4j.GraphDatabase 'http://localhost:7474'

# seed nodes into graph
users = for i in [0..6]
db.createNode
name: "traversalTest#{i}"

# node shortcut references
user0 = users[0]
user1 = users[1]
user2 = users[2]
user3 = users[3]
user4 = users[4]
user5 = users[5]
user6 = users[6]

@traverse =

'(pre-req) save nodes': (_) ->
flows.collect _,
for user in users
user.save not _

'(pre-req) create relationships': (_) ->
createFollowRelationships = (i, _) ->
user = users[i]
i1 = (i + 1) % users.length
i2 = (i + 2) % users.length
i3 = (i + 3) % users.length
flows.collect _, [
user.createRelationshipTo users[i1], 'traverse_follows', {}, not _
user.createRelationshipTo users[i2], 'traverse_follows', {}, not _
user.createRelationshipTo users[i3], 'traverse_follows', {}, not _
]

flows.collect _,
for user, i in users
createFollowRelationships i, not _

'traverse connected nodes': (_) ->
nodes = user0.traverse 'node', {
order: 'breadth_first',
return_filter: {
body: """position.endNode().getProperty('name').contains('t')""",
language: 'javascript'
},
prune_evaluator: {
body: 'none',
language: 'builtin'
},
uniqueness: 'node_global',
relationships: [{
direction: 'all',
type: 'traverse_follows'
}],
max_depth: 3
}, _

expect(nodes).to.exist
expect(nodes).to.be.an 'array'
expect(nodes).to.have.length 7
expect(nodes[0]).to.exist;

nodes.forEach (node) =>
expect(node.data).to.be.an 'object'
expect(node.data.name).to.contain 't'

for name, test of @traverse
do (name, test) =>
@traverse[name] = (_) ->
test _