stephen February 2016

from Neo4j to GraphJSON with Ruby

I'm trying to get visualizations using d3.js or alchemy.js--but alchemy, in particular, requires the datasource to be in GraphJSON.

I've been playing around with the tutorials and examples of Max De Marzi (using neography), Michael Hunger (cy2neo, js), Neo4j, and Neo4j.rb -- but I cannot seem to get all the way there. Mostly because I don't know what I'm doing--but this is how I'm trying to learn.

What I'm trying to achieve would be along the lines of: or the default visualization here:

And you can see what GraphJSON formatting should look like by finding it on this page also:

If I run the following...

get '/followers' do, "http://localhost:7474")
  query = Neo4j::Session.query('MATCH (a--(b)--(c) RETURN a,b,c LIMIT 30')
  puts "--------------"
  puts query_to_graph_json(query) 

# This is supposed to grab nodes and edges, but it never gets edges.
# It's originally from a conversation at the neo4j.rb site 

  def query_to_graph_json(query)
    nodes = {}
    edges = {}

    add_datum = do |datum|
      case datum
      when Neo4j::ActiveNode, Neo4j::Server::CypherNode
        nodes[datum.neo_id] = {
        id: datum.neo_id,
        properties: datum.props #was attributes, but kept saying that wasn't a method
      when Neo4j::ActiveRel, Neo4j::Server::CypherRelationship
        edges[[datum.start_node.neo_id, datum.end_node.neo_id]] = {
        source: datum.start_node.neo_id,
        target: datum.end_node.neo_id,
        type: datum.rel_type,
        properties: datum.props


William Lyon February 2016

This Cypher query should return the edges array as per the example format:

MATCH (a)-[r]-(b)
WITH collect(
        source: id(a),
        target: id(b),
        caption: type(r)
) AS edges
RETURN edges

Running this against some sample data, the results look like this:

            "source": 9456,
            "target": 9454,
            "caption": "LIKES"
            "source": 9456,
            "target": 9454,
            "caption": "LIKES"
            "source": 9456,
            "target": 9455,
            "caption": "LIKES"
            "source": 9454,
            "target": 9456,
            "caption": "LIKES"

Brian Underwood February 2016

I think that one problem that you're having is that, instead of matching two nodes and one relationship, you're matching three nodes and two relationships. Here's your MATCH:

MATCH (a)--(b)--(c)

It should be like:

MATCH (a)-[b]-(c)

In a MATCH clause the [] can be excluded and you can just do a raw -- (or --> or <--) which represents the relationship.

You probably want to be querying for one specific direction though. If you query bidirectionally you'll get the same relationship twice with the start and end nodes switched.

Using neo4j-core (which I biased towards as one of the maintainers ;)

nodes = []
rels = []
session.query('(source)-[rel]->(target)').pluck(:source, :rel, :target).each do |source, rel, target|
  nodes << source
  nodes << target
  rels << rel

  nodes: nodes,
  edges: rels

Also note that if you don't specify any labels your query might be slow, depending on the number of nodes). Depends on what you need ;)

Post Status

Asked in February 2016
Viewed 1,962 times
Voted 5
Answered 2 times


Leave an answer