1

I'm trying to develop a little program representing link between page on a website. I want to represent each link by a relationship, and each page by a node.

For now i'm using a little data set, and it's look like :

HOME -> PAGE 1 -> PAGE 3 -> PAGE 5
     -> PAGE 2 -> PAGE 4

After inserting all my node and relation I want to traverse my graph and print data in Json to have something like :

{
  "name": "HOME",
  "children": [
    {
      "name": "PAGE 1",
      "children": [
        {
          "name": "PAGE 3",
          "children": [
            {"name": "PAGE 5"}
          ]
        },
        {
          "name": "PAGE 2",
          "children": [
            {"name": "PAGE 4"}
          ]
        }
      ]
    }
  ]
}

Is there any function doing this, or I have to write json by my own ?

Here is my code :

private static void routing( final GraphDatabaseService graphDb )
    {
        Transaction tx = graphDb.beginTx();

        Page home, p1, p2, p3, p4, p5;

        try
        {
            home = new Page(graphDb, "http://www.site.com/");
            p1 = new Page(graphDb, "http://www.site.com/page1.html");
            p2 = new Page(graphDb, "http://www.site.com/page2.html");
            p3 = new Page(graphDb, "http://www.site.com/page3.html");
            p4 = new Page(graphDb, "http://www.site.com/page4.html");
            p5 = new Page(graphDb, "http://www.site.com/page5.html");

            home.createLinkTo(p1);
            home.createLinkTo(p2);
            p1.createLinkTo(p3);
            p2.createLinkTo(p4);
            p3.createLinkTo(p5);

            tx.success();

            tx = graphDb.beginTx();
            final TraversalDescription linkTraversal = Traversal.description().depthFirst().relationships( RelationshipTypes.LINK );

            String output = "";

            for ( Node node : linkTraversal.traverse(home.getUnderlyingNode()).nodes() )
            {
                output += node.getProperty( "url" ) + "\n";

            }

            System.out.println(output);
        }
        finally
        {
            tx.finish();
        }
    }

Code of Page class

public class Page implements Serializable{
    private static final long serialVersionUID = 1L;

    static final String URL = "url";
    private final Node underlyingNode;
    private List<Page> children = null;

    public Page( final Node node )
    {
        this.underlyingNode = node;
    }

    public Page( final GraphDatabaseService graphDb, final String url )
    {
        this.underlyingNode = graphDb.createNode();
        underlyingNode.setProperty( URL, url );
        children = new ArrayList<Page>();
    }

    public Node getUnderlyingNode()
    {
        return underlyingNode;
    }

    public String getUrl()
    {
        return (String) underlyingNode.getProperty( URL );
    }

    public void createLinkTo( final Page other )
    {
        Relationship link = underlyingNode.createRelationshipTo(other.underlyingNode, RelationshipTypes.LINK );
        children.add(other);
        //link.setProperty( ANCHOR, 'Mon ancre' );
    }

    @Override
    public String toString()
    {
        return "Page [url=" + getUrl() + "]";
    }
guillaume
  • 1,638
  • 5
  • 24
  • 43
  • I prefer to represent a graph in JSON by simply listing the nodes and edges. Each node has a unique id (could be its internal Neo id), and an edge is simply represented as a start node id and a end node id. Using any of the basic java JSON libraries out there and the `GlobalGraphOperations` class in Neo, you should be able to build up this JSON message with little code. – rmlan Feb 07 '13 at 16:34

2 Answers2

3

Assuming you have a bean representing your page, something like this:

public class Page implements Serializable {
    private String name;
    private List<Page> children;
    private transient GraphDatabaseService dbService;

    // Constructors, Getters/Setters
}

You can easily serialize this with a variety of JSON libraries like Jackson or GSON. Here is a simple Jackson example:

final Page home ; // Initialize and construct the home page
final ObjectMapper mapper = new ObjectMapper();
final String json = mapper.writeValueAsString(home);
Perception
  • 79,279
  • 19
  • 185
  • 195
  • I've used both GSON and Jackson and agree that they are easy to use and efficient. – rtcarlson Feb 07 '13 at 16:41
  • Last time I checked (August 2012) jackson suffered from problems resolving circular dependencies (take a look on http://stackoverflow.com/questions/3340485/how-to-solve-circular-reference-in-json-serializer-caused-by-hibernate-bidirecti) – aviad Feb 07 '13 at 16:59
  • Jackson has supported identity resolution since 2.0, in order to better handle circular dependencies - http://wiki.fasterxml.com/JacksonFeatureObjectIdentity. – Perception Feb 07 '13 at 17:02
  • I try this solution, but I have an infinite recursion `Infinite recursion (StackOverflowError) (through reference chain: Page["underlyingNode"]->org.neo4j.kernel.impl.core`, I add the code of Page in my first post – guillaume Feb 07 '13 at 18:42
  • Thanks, It works, now I will see how I can have the exact desired format. And it will work if I have a lot of node (like 100 000 pages) ? – guillaume Feb 07 '13 at 18:48
  • As with any large dataset your immediate concern will be memory. You may need to increase your Java heap size. In addition, do note that serialization is not necessarily cheap, and the larger the input data set the longer the serialization will take. – Perception Feb 07 '13 at 19:12
0

I think the most effective format is something like a node- and edgelist, see https://github.com/jexp/batch-import for a CSV version, D3 does something similar in Javascript, see the D3 examples that read in JSON.

/peter

Peter Neubauer
  • 6,311
  • 1
  • 21
  • 24