Sunday, March 31, 2013

Neo4j Graph Case Study - Facebook & Trip Planner

NoSQL Graph Database - Neo4j

Graphs are everywhere - social networks, routing algorithms, payment flow, and many more. Facebook friends, Twitter followers, LinkedIn graph are a few scenarios for Graph. Quite recently Facebook released Social Graph search. Neo4j is an open source NOSQL Graph database, immensely popular and being used by companies like Adobe, Intuit. Twitter uses FlockDB for the Graphs. 

Download and extract Neo4j Community edition from http://www.neo4j.org/download. Start the server by running /bin/Neo4j.bat. The Neo4j monitoring tool can be accessed from http://localhost:7474/webadmin/. The monitoring tool provides several utilities as shown below. 


Gremlin - A Groovy tool for querying Graph data


Neo4j Monitoring console


Neo4j Data Browser

Apart from the above utilities, Neo4j provides support for Graph Query language called Cypher. Since Ne04j is built on Java, it runs on JVM and can be used as a Embedded database. Or it could be used as a standalone database, through REST api. There is another interesting tool called Neoclipse which is very rich in visualizing Graphs. The following Graphs for facebook friends and railway routes are generated with Neoclipse.



Applications of Neo4j

1. Facebook friend connect

  • Login to Facebook and follow the instructions from here to download the Facebook Graph data.
  • Next, run the following program to download the Profile photos from Facebook to your local machine. The photos are used only for visualization purpose for neoclipse. This step uses the data downloaded from the previous step. change the "file" variable.
  • package com.raj.facebook.photos;
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.FileReader;
    import java.net.URL;
    import java.nio.channels.Channels;
    import java.nio.channels.ReadableByteChannel;
    public class PhotoFetcher {
    public static void main(String[] args) throws Exception {
    String dir = "C:\\Project\\workspace\\FacebookGraph\\resources\\images\\";
    File file = new File("C:\\Project\\workspace\\FacebookGraph\\resources\\Raju Ramakrishna_1364522831.graphml");
    BufferedReader br = new BufferedReader(new FileReader(file));
    String line = br.readLine();
    String url = null;
    String name = null;
    while( line != null ) {
    if( line.indexOf("<data key=\"pic_big\">") != -1 ) {
    if(line.indexOf(".jpg") != -1)
    url = line.substring(line.indexOf("http:"), line.indexOf(".jpg")+4);
    else
    url = line.substring(line.indexOf("http:"), line.indexOf(".gif")+4);
    URL picUrl = new URL(url);
    File outFile = new File(dir+ name + ".jpg");
    ReadableByteChannel rbc = Channels.newChannel(picUrl.openStream());
    FileOutputStream fos = new FileOutputStream(outFile);
    fos.getChannel().transferFrom(rbc, 0, 1 << 24);
    fos.close();
    }
    if( line.indexOf("node id") != -1) {
    name = line.substring(10, line.length()-2);
    }
    line = br.readLine();
    if( line.indexOf("edge id") != -1) {
    break;
    }
    }
    br.close();
    }
    }
    view raw gistfile1.java hosted with ❤ by GitHub
  • The next step is to import the graph data to Neo4j. Run the below program. I have used the data for two Facebook profiles and loaded all the friends and interconnection data.
    package com.raj.facebook.graph;
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileReader;
    import org.neo4j.graphalgo.GraphAlgoFactory;
    import org.neo4j.graphalgo.PathFinder;
    import org.neo4j.graphdb.GraphDatabaseService;
    import org.neo4j.graphdb.Node;
    import org.neo4j.graphdb.Path;
    import org.neo4j.graphdb.Relationship;
    import org.neo4j.graphdb.RelationshipType;
    import org.neo4j.graphdb.Transaction;
    import org.neo4j.graphdb.factory.GraphDatabaseFactory;
    import org.neo4j.graphdb.index.IndexHits;
    import org.neo4j.kernel.Traversal;
    public class GraphUtils {
    public static final String DB_PATH="c://apps//neo4j-1.8.2//facebook";
    public static GraphDatabaseService graphDb = null;
    public static final String ID = "id";
    public static final String USER = "user:";
    public static void main(String[] args) throws Exception {
    new GraphUtils().createGraph();
    }
    public void createGraph() throws Exception {
    graphDb = new GraphDatabaseFactory().newEmbeddedDatabase( DB_PATH );
    registerShutdownHook( graphDb );
    File file = new File("C:\\Project\\workspace\\FacebookGraph\\resources\\Raju Ramakrishna_1364522831.graphml");
    BufferedReader br = new BufferedReader(new FileReader(file));
    String line = br.readLine();
    Node node = null;
    String key = null;
    String val = null;
    String source = null;
    String target = null;
    Transaction tx = graphDb.beginTx();
    Node myself = graphDb.createNode();
    myself.setProperty("fb_id", "Raju_Ramakrishna_100000243684316");
    myself.setProperty("uid", "100000243684316");
    myself.setProperty("name", "Raju Ramakrishna");
    myself.setProperty("sex", "male");
    myself.setProperty("mutual_friends", 27);
    myself.setProperty("likes", 16);
    myself.setProperty("friend_count", 180);
    graphDb.index().forNodes("myfriends").add(myself, "fb_id", "Raju_Ramakrishna_100000243684316");
    while( line != null ) {
    if(line.indexOf("node id") != -1) {
    val = line.substring(line.indexOf("node id")+9, line.length()-2);
    System.out.println("ID=" +val);
    node = graphDb.createNode();
    node.setProperty("fb_id", val);
    graphDb.index().forNodes("myfriends").add(node, "fb_id", val);
    Relationship relationship = myself.createRelationshipTo(node, RelTypes.FRIEND);
    relationship.setProperty("link", myself.getProperty("fb_id") + " <==> " +node.getProperty("fb_id"));
    } else if(line.indexOf("</node>") != -1) {
    System.out.println("----------");
    } else if(line.indexOf("data key") != -1){
    if(line.indexOf("uid") != -1) {
    key = "CDATA";
    val = line.substring(line.indexOf(key)+key.length()+1, line.indexOf("</data>")-3);
    System.out.println("Label = " +val);
    node.setProperty("uid", val);
    } else if(line.indexOf("name") != -1) {
    key = "CDATA";
    val = line.substring(line.indexOf(key)+key.length()+1, line.indexOf("</data>")-3);
    System.out.println("Name = " +val);
    node.setProperty("name", val);
    } else if(line.indexOf("sex") != -1) {
    key = "CDATA";
    val = line.substring(line.indexOf(key)+key.length()+1, line.indexOf("</data>")-3);
    System.out.println("Sex = " +val);
    node.setProperty("sex", val);
    } else if(line.indexOf("mutual_friend_count") != -1) {
    key = "CDATA";
    val = line.substring(line.indexOf(key)+key.length()+1, line.indexOf("</data>")-3);
    System.out.println("Mutual Friends = " +val);
    node.setProperty("mutual_friends", val);
    } else if(line.indexOf("likes_count") != -1) {
    key = "CDATA";
    val = line.substring(line.indexOf(key)+key.length()+1, line.indexOf("</data>")-3);
    System.out.println("Likes = " +val);
    node.setProperty("likes", val);
    } else if(line.indexOf("friend_count") != -1) {
    key = "CDATA";
    val = line.substring(line.indexOf(key)+key.length()+1, line.indexOf("</data>")-3);
    System.out.println("Friends = " +val);
    node.setProperty("friend_count", val);
    } else if(line.indexOf("pic_big") != -1) {
    key = "CDATA";
    val = line.substring(line.indexOf(key)+key.length()+1, line.indexOf("</data>")-3);
    System.out.println("picture = " +val);
    // node.setProperty("picture", val);
    }
    } else if(line.indexOf("edge id") != -1) {
    source = line.substring(line.indexOf("source")+8, line.indexOf("target")-2);
    target = line.substring(line.indexOf("target")+8, line.indexOf("</edge>")-2);
    System.out.println(source+ " ---- " +target);
    Node sourceNode = graphDb.index().forNodes("myfriends").get("fb_id", source).next();
    Node targetNode = graphDb.index().forNodes("myfriends").get("fb_id", target).next();
    Relationship relationship = sourceNode.createRelationshipTo(targetNode, RelTypes.FRIEND);
    relationship.setProperty("link", sourceNode.getProperty("fb_id") + " <==> " +targetNode.getProperty("fb_id"));
    }
    line = br.readLine();
    }
    br.close();
    file = new File("C:\\Project\\workspace\\FacebookGraph\\resources\\Geeta Raj_1364532420.graphml");
    br = new BufferedReader(new FileReader(file));
    line = br.readLine();
    boolean nodeFound = false;
    myself = graphDb.index().forNodes("myfriends").get("fb_id", "Geeta_Raj_556485423").next();
    while( line != null ) {
    if(line.indexOf("node id") != -1) {
    val = line.substring(line.indexOf("node id")+9, line.length()-2);
    System.out.println("ID=" +val);
    IndexHits<Node> nodes = graphDb.index().forNodes("myfriends").get("fb_id", val);
    if( nodes.hasNext() ) {
    node = nodes.next();
    nodeFound = true;
    } else {
    node = graphDb.createNode();
    node.setProperty("fb_id", val);
    graphDb.index().forNodes("myfriends").add(node, "fb_id", val);
    Relationship relationship = myself.createRelationshipTo(node, RelTypes.FRIEND);
    relationship.setProperty("link", myself.getProperty("fb_id") + " <==> " +node.getProperty("fb_id"));
    }
    } else if(line.indexOf("</node>") != -1) {
    nodeFound = false;
    System.out.println("----------");
    } else if( !nodeFound && line.indexOf("data key") != -1){
    if(line.indexOf("uid") != -1) {
    key = "CDATA";
    val = line.substring(line.indexOf(key)+key.length()+1, line.indexOf("</data>")-3);
    System.out.println("Label = " +val);
    node.setProperty("uid", val);
    } else if(line.indexOf("name") != -1) {
    key = "CDATA";
    val = line.substring(line.indexOf(key)+key.length()+1, line.indexOf("</data>")-3);
    System.out.println("Name = " +val);
    node.setProperty("name", val);
    } else if(line.indexOf("sex") != -1) {
    key = "CDATA";
    val = line.substring(line.indexOf(key)+key.length()+1, line.indexOf("</data>")-3);
    System.out.println("Sex = " +val);
    node.setProperty("sex", val);
    } else if(line.indexOf("mutual_friend_count") != -1) {
    key = "CDATA";
    val = line.substring(line.indexOf(key)+key.length()+1, line.indexOf("</data>")-3);
    System.out.println("Mutual Friends = " +val);
    node.setProperty("mutual_friends", val);
    } else if(line.indexOf("likes_count") != -1) {
    key = "CDATA";
    val = line.substring(line.indexOf(key)+key.length()+1, line.indexOf("</data>")-3);
    System.out.println("Likes = " +val);
    node.setProperty("likes", val);
    } else if(line.indexOf("friend_count") != -1) {
    key = "CDATA";
    val = line.substring(line.indexOf(key)+key.length()+1, line.indexOf("</data>")-3);
    System.out.println("Friends = " +val);
    node.setProperty("friend_count", val);
    } else if(line.indexOf("pic_big") != -1) {
    key = "CDATA";
    val = line.substring(line.indexOf(key)+key.length()+1, line.indexOf("</data>")-3);
    System.out.println("picture = " +val);
    // node.setProperty("picture", val);
    }
    } else if(line.indexOf("edge id") != -1) {
    source = line.substring(line.indexOf("source")+8, line.indexOf("target")-2);
    target = line.substring(line.indexOf("target")+8, line.indexOf("</edge>")-2);
    System.out.println(source+ " ---- " +target);
    Node sourceNode = graphDb.index().forNodes("myfriends").get("fb_id", source).next();
    Node targetNode = graphDb.index().forNodes("myfriends").get("fb_id", target).next();
    //Only if there is no link already
    PathFinder<Path> finder = GraphAlgoFactory.shortestPath(
    Traversal.expanderForTypes( RelTypes.FRIEND ), 1 );
    Iterable<Path> paths = finder.findAllPaths( sourceNode, targetNode );
    if(!paths.iterator().hasNext()) {
    Relationship relationship = sourceNode.createRelationshipTo(targetNode, RelTypes.FRIEND);
    relationship.setProperty("link", sourceNode.getProperty("fb_id") + " <==> " +targetNode.getProperty("fb_id"));
    }
    }
    line = br.readLine();
    }
    br.close();
    tx.success();
    tx.finish();
    }
    public static enum RelTypes implements RelationshipType {
    FRIEND
    }
    private static void registerShutdownHook( final GraphDatabaseService graphDb )
    {
    // Registers a shutdown hook for the Neo4j instance so that it
    // shuts down nicely when the VM exits (even if you "Ctrl-C" the
    // running example before it's completed)
    Runtime.getRuntime().addShutdownHook( new Thread()
    {
    @Override
    public void run()
    {
    graphDb.shutdown();
    }
    } );
    }
    }
    view raw gistfile1.java hosted with ❤ by GitHub
  • Now the data is ready, I implemented a search utility which - given 2 Facebook IDs, it will provide all posible ways for the 2 people to get connected. 
    package com.raj.facebook.graph;
    import org.neo4j.graphalgo.GraphAlgoFactory;
    import org.neo4j.graphalgo.PathFinder;
    import org.neo4j.graphdb.GraphDatabaseService;
    import org.neo4j.graphdb.Node;
    import org.neo4j.graphdb.Path;
    import org.neo4j.graphdb.Relationship;
    import org.neo4j.graphdb.RelationshipType;
    import org.neo4j.graphdb.factory.GraphDatabaseFactory;
    import org.neo4j.kernel.Traversal;
    public class SearchFriends {
    public static final String DB_PATH="c://apps//neo4j-1.8.2//facebook";
    public static GraphDatabaseService graphDb = null;
    public static final String ID = "id";
    public static final String USER = "user:";
    public static void main(String[] args) throws Exception {
    new SearchFriends().search();
    }
    public void search() throws Exception {
    graphDb = new GraphDatabaseFactory().newEmbeddedDatabase( DB_PATH );
    registerShutdownHook( graphDb );
    Node you = graphDb.index().forNodes("myfriends").get("fb_id", "Raju_Ramakrishna_100000243684316").next();
    Node me = graphDb.index().forNodes("myfriends").get("fb_id", "Geeta_Madye_1178898406").next();
    PathFinder<Path> finder = GraphAlgoFactory.shortestPath(
    Traversal.expanderForTypes( RelTypes.FRIEND ), 2 );
    Iterable<Path> paths = finder.findAllPaths( you, me );
    for( Path path: paths ) {
    for( Relationship relation: path.relationships()) {
    System.out.println(relation.getProperty("link"));
    }
    System.out.println();
    }
    }
    public static enum RelTypes implements RelationshipType {
    FRIEND
    }
    private static void registerShutdownHook( final GraphDatabaseService graphDb )
    {
    // Registers a shutdown hook for the Neo4j instance so that it
    // shuts down nicely when the VM exits (even if you "Ctrl-C" the
    // running example before it's completed)
    Runtime.getRuntime().addShutdownHook( new Thread()
    {
    @Override
    public void run()
    {
    graphDb.shutdown();
    }
    } );
    }
    }
    view raw gistfile1.java hosted with ❤ by GitHub

2. Railway Trip Planner

  • For this application, I used data from Indian Railways site. A few trains were randomly chosen and their routes and information were stored in local file system as a tab-delimited text. The route information contains station code, names, distances, time taken etc.  I created directories with name as train number. Each directory contains info.csv and schedule.csv. Download it and save the directories and its contents locally. It can be downloaded from here
  • Next, run the below program to import the graph data to Neo4j.
    package com.raj.railways;
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileReader;
    import org.neo4j.graphdb.GraphDatabaseService;
    import org.neo4j.graphdb.Node;
    import org.neo4j.graphdb.Relationship;
    import org.neo4j.graphdb.RelationshipType;
    import org.neo4j.graphdb.Transaction;
    import org.neo4j.graphdb.factory.GraphDatabaseFactory;
    import org.neo4j.graphdb.index.IndexHits;
    public class DataLoader {
    public static final String DB_PATH="c://apps//neo4j-1.8.2//indianrail";
    public static GraphDatabaseService graphDb = null;
    /**
    * @param args
    */
    public static void main(String[] args) throws Exception {
    graphDb = new GraphDatabaseFactory().newEmbeddedDatabase( DB_PATH );
    registerShutdownHook( graphDb );
    Transaction tx = graphDb.beginTx();
    String loc = "C:\\Project\\dataset\\indian-railways\\";
    File mainDir = new File(loc);
    String[] dirs = mainDir.list();
    for( String s: dirs ) {
    File dir = new File(loc+"\\"+s);
    // System.out.println(dir.getName());
    File file = new File(loc + "\\" +s+ "\\info.csv");
    BufferedReader br = new BufferedReader(new FileReader(file));
    String line = br.readLine();
    String trainNumber = null;
    String trainName = null;
    while(line != null) {
    line = br.readLine();
    if( line != null ) {
    String[] sArr = line.split("\t");
    trainNumber = sArr[0];
    trainName = sArr[1];
    System.out.println(trainNumber+":"+trainName);
    }
    }
    br.close();
    Train train = new Train( trainNumber, trainName );
    file = new File(loc + "\\" +s+ "\\schedule.csv");
    br = new BufferedReader(new FileReader(file));
    line = br.readLine();
    int dist = -1;
    Node previousNode = null;
    while(line != null) {
    line = br.readLine();
    if( line != null ) {
    String[] sArr = line.split("\t");
    String stationCode = sArr[1];
    String stationName = sArr[2];
    int totalDist = Integer.parseInt(sArr[7]);
    if( dist == -1 ) {
    dist =0;
    }
    System.out.println(stationCode+":"+stationName+ " ~ " +(totalDist-dist));
    IndexHits<Node> nodes = graphDb.index().forNodes("station").get("code", stationCode);
    Node node = null;
    if( nodes.hasNext() ) {
    node = nodes.next();
    String trains = (String)node.getProperty("trains");
    trains = trains + "|" +train.toString();
    node.setProperty("trains", trains);
    } else {
    node = graphDb.createNode();
    node.setProperty("code", stationCode);
    node.setProperty("name", stationName);
    node.setProperty("trains", train.toString());
    graphDb.index().forNodes("station").add( node, "code", stationCode);
    }
    if( previousNode != null ) {
    String prevCode = (String)previousNode.getProperty("code");
    String relation = prevCode + "-" +stationCode;
    if(!graphDb.index().forRelationships("route").get("path", relation).hasNext()) {
    Relationship relationship = previousNode.createRelationshipTo(node, RelTypes.ROUTE);
    relationship.setProperty("distance", (totalDist-dist));
    graphDb.index().forRelationships("route").add(relationship, "path", relation);
    }
    }
    dist = totalDist;
    previousNode = node;
    }
    }
    br.close();
    }
    tx.success();
    tx.finish();
    }
    public static enum RelTypes implements RelationshipType {
    ROUTE
    }
    private static void registerShutdownHook( final GraphDatabaseService graphDb )
    {
    // Registers a shutdown hook for the Neo4j instance so that it
    // shuts down nicely when the VM exits (even if you "Ctrl-C" the
    // running example before it's completed)
    Runtime.getRuntime().addShutdownHook( new Thread()
    {
    @Override
    public void run()
    {
    graphDb.shutdown();
    }
    } );
    }
    }
    class Train {
    String trainNumber;
    String trainName;
    public Train(String trainNumber, String trainName) {
    super();
    this.trainNumber = trainNumber;
    this.trainName = trainName;
    }
    public String toString() {
    return trainNumber + "~" +trainName;
    }
    }
    view raw gistfile1.java hosted with ❤ by GitHub
  • Now the data is available, I created a trip planner. It provides 2 options - Search for a path between 2 stations with least distance, Search for a path between 2 stations with least number of stops. In each case print the total distance. 
    package com.raj.railways;
    import java.util.HashSet;
    import java.util.Set;
    import org.neo4j.graphalgo.GraphAlgoFactory;
    import org.neo4j.graphalgo.PathFinder;
    import org.neo4j.graphalgo.WeightedPath;
    import org.neo4j.graphdb.Direction;
    import org.neo4j.graphdb.GraphDatabaseService;
    import org.neo4j.graphdb.Node;
    import org.neo4j.graphdb.Path;
    import org.neo4j.graphdb.Relationship;
    import org.neo4j.graphdb.RelationshipType;
    import org.neo4j.graphdb.factory.GraphDatabaseFactory;
    import org.neo4j.kernel.Traversal;
    public class TrainSearch {
    public static final String DB_PATH="c://apps//neo4j-1.8.2//indianrail";
    public static GraphDatabaseService graphDb = null;
    /**
    * @param args
    */
    public static void main(String[] args) throws Exception {
    graphDb = new GraphDatabaseFactory().newEmbeddedDatabase( DB_PATH );
    registerShutdownHook( graphDb );
    new TrainSearch().search("SBC", "UBL");
    System.out.println();
    new TrainSearch().search("UBL", "BGM");
    }
    public void search( String code1, String code2 ) {
    System.out.println("**************************************");
    Node source = graphDb.index().forNodes("station").get("code", code1).next();
    Node target = graphDb.index().forNodes("station").get("code", code2).next();
    System.out.println("SOURCE: " +source.getProperty("name")+ " DESTINATION: " +target.getProperty("name"));
    //Get Least number of stops
    System.out.println();
    System.out.println("Route for least number of Stops");
    PathFinder<Path> finder = GraphAlgoFactory.shortestPath(
    Traversal.expanderForTypes( RelTypes.ROUTE ), 200 );
    Path path = finder.findAllPaths( source, target ).iterator().next();
    int total = 0;
    for(Node node : path.nodes()) {
    System.out.print(node.getProperty("name") + " -> ");
    }
    System.out.println();
    for( Relationship relation: path.relationships()) {
    total += (int)relation.getProperty("distance");
    }
    System.out.println();
    System.out.println("Distance = " +total+ " KM");
    PathFinder<WeightedPath> weightedFinder = GraphAlgoFactory.dijkstra(
    Traversal.expanderForTypes( RelTypes.ROUTE, Direction.BOTH ), "distance" );
    WeightedPath weightedPath = weightedFinder.findSinglePath( source, target );
    // Get the weight for the found path
    double weight = weightedPath.weight();
    System.out.println();
    System.out.println("Route for minimum distance");
    for(Node node : weightedPath.nodes()) {
    System.out.print(node.getProperty("name") + " -> ");
    }
    System.out.println();
    System.out.println("Distance = " +(int)weight+ " KM");
    }
    public static enum RelTypes implements RelationshipType {
    ROUTE
    }
    private static void registerShutdownHook( final GraphDatabaseService graphDb )
    {
    // Registers a shutdown hook for the Neo4j instance so that it
    // shuts down nicely when the VM exits (even if you "Ctrl-C" the
    // running example before it's completed)
    Runtime.getRuntime().addShutdownHook( new Thread()
    {
    @Override
    public void run()
    {
    graphDb.shutdown();
    }
    } );
    }
    }
    view raw gistfile1.java hosted with ❤ by GitHub
  • The output of the above search program is
    SOURCE: BANGALORE CY JN DESTINATION: HUBLI JN
    Route for least number of Stops
    BANGALORE CY JN -> YESVANTPUR JN -> DHARMAVARAM JN -> ANANTAPUR -> GUNTAKAL JN -> BELLARY JN -> HOSPET JN -> KOPPAL -> GADAG JN -> HUBLI JN ->
    Distance = 541 KM
    Route for minimum distance
    BANGALORE CY JN -> YESVANTPUR JN -> TUMKUR -> AMMASANDRA -> TIPTUR -> ARSIKERE JN -> KADUR -> BIRUR JN -> DAVANGERE -> HARIHAR -> RANIBENNUR -> HAVERI -> HUBLI JN ->
    Distance = 469 KM
    view raw gistfile1.txt hosted with ❤ by GitHub

3. Facebook Graph Search

  • Facebook Graph Search is released. It provides search based on your friends connections, likes and recommendations. So I could ask it for "Suggest me Indian Vegetarian restaurants in and around South London". There is a wonderful article on how to build this with Neo4j at http://jimwebber.org/2013/02/neo4j-facebook-graphsearch-for-the-rest-of-us/
  • I implemented the code based on the above design.  First build the Graph <
    package com.raj.socialgraph;
    import org.neo4j.graphdb.GraphDatabaseService;
    import org.neo4j.graphdb.Node;
    import org.neo4j.graphdb.RelationshipType;
    import org.neo4j.graphdb.Transaction;
    import org.neo4j.graphdb.factory.GraphDatabaseFactory;
    public class SocialGraph {
    public static final String DB_PATH="c://apps//neo4j-1.8.2//socialgraph";
    public static GraphDatabaseService graphDb = null;
    /**
    * @param args
    */
    public static void main(String[] args) {
    graphDb = new GraphDatabaseFactory().newEmbeddedDatabase( DB_PATH );
    registerShutdownHook( graphDb );
    Transaction tx = graphDb.beginTx();
    loadData();
    tx.success();
    tx.finish();
    System.out.println("Created Social Graph!!");
    }
    public static void loadData() {
    Node jim = graphDb.createNode();
    jim.setProperty("name", "Jim");
    graphDb.index().forNodes("name").add(jim, "name", "Jim");
    Node kath = graphDb.createNode();
    kath.setProperty("name", "Kath");
    graphDb.index().forNodes("name").add(kath, "name", "Kath");
    Node martin = graphDb.createNode();
    martin.setProperty("name", "Martin");
    graphDb.index().forNodes("name").add(martin, "name", "Martin");
    Node simon = graphDb.createNode();
    simon.setProperty("name", "Simon");
    graphDb.index().forNodes("name").add(simon, "name", "Simon");
    jim.createRelationshipTo(kath, RelTypes.FRIEND);
    jim.createRelationshipTo(martin, RelTypes.FRIEND);
    jim.createRelationshipTo(simon, RelTypes.FRIEND);
    martin.createRelationshipTo(simon, RelTypes.FRIEND);
    Node tandooriNights = graphDb.createNode();
    tandooriNights.setProperty("restaurant", "Tandoori Nights");
    graphDb.index().forNodes("restaurant").add(tandooriNights, "name", "Tandoori Nights");
    Node indianMischief = graphDb.createNode();
    indianMischief.setProperty("restaurant", "Indian Mischief");
    graphDb.index().forNodes("restaurant").add(indianMischief, "name", "Indian Mischief");
    Node babur = graphDb.createNode();
    babur.setProperty("restaurant", "Babur");
    graphDb.index().forNodes("restaurant").add(babur, "name", "Babur");
    Node indian = graphDb.createNode();
    indian.setProperty("category", "Indian");
    graphDb.index().forNodes("category").add(indian, "name", "Indian");
    Node vegetarian = graphDb.createNode();
    vegetarian.setProperty("category", "Vegetarian");
    graphDb.index().forNodes("category").add(vegetarian, "name", "Vegetarian");
    tandooriNights.createRelationshipTo(indian, RelTypes.CUISINE);
    indianMischief.createRelationshipTo(indian, RelTypes.CUISINE);
    babur.createRelationshipTo(indian, RelTypes.CUISINE);
    indianMischief.createRelationshipTo(vegetarian, RelTypes.CUISINE);
    Node eastDulwich = graphDb.createNode();
    eastDulwich.setProperty("neighbourhood", "East Dulwich");
    graphDb.index().forNodes("neighbourhood").add(eastDulwich, "name", "East Dulwich");
    Node forestHill = graphDb.createNode();
    forestHill.setProperty("neighbourhood", "Forest Hill");
    graphDb.index().forNodes("neighbourhood").add(forestHill, "name", "Forest Hill");
    tandooriNights.createRelationshipTo(eastDulwich, RelTypes.IN);
    indianMischief.createRelationshipTo(eastDulwich, RelTypes.IN);
    babur.createRelationshipTo(forestHill, RelTypes.IN);
    Node southwark = graphDb.createNode();
    southwark.setProperty("borough", "Southwark");
    graphDb.index().forNodes("borough").add(southwark, "name", "Southwark");
    Node southLondon = graphDb.createNode();
    southLondon.setProperty("area", "South London");
    graphDb.index().forNodes("area").add(southLondon, "name", "South London");
    Node london = graphDb.createNode();
    london.setProperty("city", "London");
    graphDb.index().forNodes("city").add(london, "name", "London");
    eastDulwich.createRelationshipTo(southwark, RelTypes.IN);
    forestHill.createRelationshipTo(southwark, RelTypes.IN);
    southwark.createRelationshipTo(southLondon, RelTypes.IN);
    southLondon.createRelationshipTo(london, RelTypes.IN);
    jim.createRelationshipTo(tandooriNights, RelTypes.LIKES);
    kath.createRelationshipTo(tandooriNights, RelTypes.LIKES);
    martin.createRelationshipTo(babur, RelTypes.LIKES);
    simon.createRelationshipTo(babur, RelTypes.LIKES);
    }
    public static enum RelTypes implements RelationshipType {
    FRIEND,
    CUISINE,
    LIKES,
    IN
    }
    private static void registerShutdownHook( final GraphDatabaseService graphDb )
    {
    Runtime.getRuntime().addShutdownHook( new Thread()
    {
    @Override
    public void run()
    {
    graphDb.shutdown();
    }
    } );
    }
    }
    view raw gistfile1.java hosted with ❤ by GitHub
  • Next run search on restaurants
    package com.raj.socialgraph;
    import org.neo4j.cypher.ExecutionEngine;
    import org.neo4j.cypher.ExecutionResult;
    import org.neo4j.graphdb.GraphDatabaseService;
    import org.neo4j.graphdb.factory.GraphDatabaseFactory;
    import org.neo4j.kernel.impl.util.StringLogger;
    import scala.collection.immutable.Map;
    public class Recommender {
    public static final String DB_PATH="c://apps//neo4j-1.8.2//socialgraph";
    public static GraphDatabaseService graphDb = null;
    /**
    * @param args
    */
    public static void main(String[] args) {
    graphDb = new GraphDatabaseFactory().newEmbeddedDatabase( DB_PATH );
    registerShutdownHook( graphDb );
    ExecutionEngine engine = new ExecutionEngine(graphDb, StringLogger.SYSTEM );
    String query = new StringBuffer("START jim = node:name(name='Jim'),")
    .append(" southwark = node:borough(name='Southwark'),")
    .append(" indian = node:category(name='Indian')")
    .append(" MATCH jim-[:FRIEND]->friend-[:LIKES]->restaurant-[:IN]->()-[:IN]->southwark,")
    .append(" restaurant-[:CUISINE]->indian,")
    .append(" jim-[:LIKES]->myrestaurant")
    .append(" WHERE restaurant.restaurant <> myrestaurant.restaurant")
    .append(" RETURN distinct restaurant.restaurant;").toString();
    ExecutionResult result = engine.execute( query );
    Map<String, Object> map = result.next();
    System.out.println( map.get("restaurant.restaurant") );
    }
    private static void registerShutdownHook( final GraphDatabaseService graphDb )
    {
    Runtime.getRuntime().addShutdownHook( new Thread()
    {
    @Override
    public void run()
    {
    graphDb.shutdown();
    }
    } );
    }
    }
    view raw gistfile1.java hosted with ❤ by GitHub

High Availability

Neo4j enterprise edition provides high availability in the form of replication and shard caching. I tried this on a 63 Million Node relationships with a cluster of 3 nodes. Planning to write up in next series....

5 comments:

  1. Hi Raju,
    Thanks for share the Neo4j work.
    I am trying to run the "Railway Trip Planner" example. But doesn't able to get the .csv file. The here link is broken. Can you share the csv files.
    Regards,
    Animesh

    ReplyDelete
    Replies
    1. Thanks Animesh .. my mistake!!

      I have fixed it now.

      Delete
  2. Hi Raju,

    Trying Railway Trip Planner example. I'm getting following error,
    Caused by: java.lang.ClassNotFoundException: javax.transaction.TransactionManager

    at graphDb = new GraphDatabaseFactory().newEmbeddedDatabase( DB_PATH );

    Where should I point DB_PATH to?

    Thanks,
    Vrushali.

    ReplyDelete
  3. Hi,
    Thanks for share this code.
    i have a question for you:
    Do you have any idea, how i can use Dijkstra Algoritm to find not only 1 path with lower distance, but the first 3?

    ReplyDelete
  4. Harrah's Casino & Racetrack | New Orleans, LA - MapYR
    Harrah's Casino & 수원 출장마사지 Racetrack in New Orleans, LA 사천 출장안마 has 안양 출장샵 one of the most luxurious rooms in 통영 출장샵 the world, a large casino, and 동해 출장샵 an upscale live entertainment

    ReplyDelete

UA-36403895-1