Skip to content

Commit

Permalink
pagerank working
Browse files Browse the repository at this point in the history
  • Loading branch information
maxdemarzi committed Mar 28, 2015
1 parent ad73c3a commit 76373c3
Show file tree
Hide file tree
Showing 6 changed files with 828 additions and 2 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*.iml
.idea
target
neo4j
45 changes: 43 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,43 @@
# graph_processing
Graph Processing Algorithms on top of Neo4j
Graph Processing
================

This is an unmanaged extension with Graph Processing Algorithms on top of Neo4j.

1. Build it:

mvn clean package

2. Copy target/graph-processing-1.0.jar to the plugins/ directory of your Neo4j server.

mv target/graph-processing-1.0.jar neo4j/plugins/.

3. Download additional jars to the plugins/ directory of your Neo4j server.

curl -O http://central.maven.org/maven2/it/unimi/dsi/fastutil/7.0.2/fastutil-7.0.2.jar
mv fastutil-7.0.2.jar neo4j/plugins/.

4. Configure Neo4j by adding a line to conf/neo4j-server.properties:

org.neo4j.server.thirdparty_jaxrs_classes=com.maxdemarzi.processing=/service

5. Start Neo4j server.

6. Create the Movie Dataset:

play :movies

7. Create KNOWS relationships amongst actors:

MATCH (a1:Person)-[:ACTED_IN]->(m)<-[:ACTED_IN]-(coActors)
CREATE (a1)-[:KNOWS]->(coActors);

8. Call the pagerank endpoint:

curl http://neo4j:swordfish@localhost:7474/service/v1/pagerank/Person/KNOWS

You should see "PageRank for Person and KNOWS Completed!"

9. Check the pageranks of some nodes:

MATCH (n:Person) RETURN n ORDER BY n.pagerank DESC LIMIT 10;

113 changes: 113 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.maxdemarzi</groupId>
<artifactId>graph-processing</artifactId>
<version>1.0</version>

<properties>
<neo4j.version>2.2.0</neo4j.version>
<guava.version>18.0</guava.version>
<jmh.version>1.6.1</jmh.version>
<fastutil.version>7.0.2</fastutil.version>
</properties>

<dependencies>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j</artifactId>
<version>${neo4j.version}</version>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-kernel</artifactId>
<type>test-jar</type>
<version>${neo4j.version}</version>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>server-api</artifactId>
<version>${neo4j.version}</version>
</dependency>
<dependency>
<groupId>org.neo4j.app</groupId>
<artifactId>neo4j-server</artifactId>
<version>${neo4j.version}</version>
</dependency>
<dependency>
<groupId>org.neo4j.app</groupId>
<artifactId>neo4j-server</artifactId>
<version>${neo4j.version}</version>
<type>test-jar</type>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-io</artifactId>
<type>test-jar</type>
<version>${neo4j.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.9</version>
</dependency>

<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>${jmh.version}</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>${jmh.version}</version>
</dependency>

<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>

<dependency>
<groupId>it.unimi.dsi</groupId>
<artifactId>fastutil</artifactId>
<version>${fastutil.version}</version>
</dependency>

<dependency>
<groupId>net.openhft</groupId>
<artifactId>koloboke-api-jdk6-7</artifactId>
<version>0.6.6</version>
</dependency>
<dependency>
<groupId>net.openhft</groupId>
<artifactId>koloboke-impl-jdk6-7</artifactId>
<version>0.6.6</version>
<scope>runtime</scope>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>

</project>
93 changes: 93 additions & 0 deletions src/main/java/com/maxdemarzi/processing/Service.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package com.maxdemarzi.processing;

import it.unimi.dsi.fastutil.longs.Long2DoubleMap;
import it.unimi.dsi.fastutil.longs.Long2DoubleOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2LongMap;
import it.unimi.dsi.fastutil.longs.Long2LongOpenHashMap;
import org.neo4j.graphdb.*;
import org.neo4j.tooling.GlobalGraphOperations;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Context;

@Path("/v1")
public class Service {
private Long2DoubleMap srcMap;
private Long2DoubleMap dstMap;
private Long2LongMap degreeMap;

private static final double ALPHA = 0.85;
private static final double ONE_MINUS_ALPHA = 1 - ALPHA;

@GET
@Path("/helloworld")
public String helloWorld() {
return "Hello World!";
}

@GET
@Path("/warmup")
public String warmUp(@Context GraphDatabaseService db) {
try ( Transaction tx = db.beginTx()) {
for ( Node n : GlobalGraphOperations.at(db).getAllNodes()) {
n.getPropertyKeys();
for ( Relationship relationship : n.getRelationships()) {
relationship.getPropertyKeys();
relationship.getStartNode();
}
}
}
return "Warmed up and ready to go!";
}

@GET
@Path("/pagerank/{label}/{type}")
public String pageRank(@PathParam("label") String label,
@PathParam("type") String type,
@Context GraphDatabaseService db) {
srcMap = new Long2DoubleOpenHashMap();
dstMap = new Long2DoubleOpenHashMap();
degreeMap = new Long2LongOpenHashMap();

RelationshipType relationshipType = DynamicRelationshipType.withName(type);

try ( Transaction tx = db.beginTx()) {
ResourceIterator<Node> nodes = db.findNodes(DynamicLabel.label(label));
while (nodes.hasNext()) {
Node node = nodes.next();
srcMap.put(node.getId(), 0);
dstMap.put(node.getId(), 0);
degreeMap.put(node.getId(), node.getDegree(relationshipType, Direction.OUTGOING));
}

for (int iteration = 0; iteration < 20; iteration++) {
nodes = db.findNodes(DynamicLabel.label(label));
while (nodes.hasNext()) {
Node node = nodes.next();
srcMap.put(node.getId(), ALPHA * dstMap.get(node.getId()) / degreeMap.get(node.getId()));
dstMap.put(node.getId(), ONE_MINUS_ALPHA);
}

for( Relationship relationship : GlobalGraphOperations.at(db).getAllRelationships()) {
if (relationship.isType(relationshipType)) {
long x = relationship.getStartNode().getId();
long y = relationship.getEndNode().getId();
dstMap.put(y, (dstMap.get(y) + srcMap.get(x)));
}
}
}

nodes = db.findNodes(DynamicLabel.label(label));
while (nodes.hasNext()) {
Node node = nodes.next();
node.setProperty("pagerank", dstMap.get(node.getId()));
}
tx.success();
}

return "PageRank for " + label + " and " + type + " Completed!";
}

}
59 changes: 59 additions & 0 deletions src/test/java/com/maxdemarzi/processing/PageRankTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.maxdemarzi.processing;

import org.codehaus.jackson.map.ObjectMapper;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.neo4j.graphdb.*;
import org.neo4j.test.TestGraphDatabaseFactory;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import static org.junit.Assert.assertEquals;

public class PageRankTest {
private GraphDatabaseService db;
private static Service service;
private static final ObjectMapper objectMapper = new ObjectMapper();
private static final Label label = DynamicLabel.label("Person");
private static final RelationshipType relationshipType = DynamicRelationshipType.withName("KNOWS");

@Before
public void setUp() {
db = new TestGraphDatabaseFactory().newImpermanentDatabase();
service = new Service();
populateDb(db);
}

private void populateDb(GraphDatabaseService db) {
try ( Transaction tx = db.beginTx()) {
db.execute(TestObjects.MOVIES_QUERY);
db.execute(TestObjects.KNOWS_QUERY);
tx.success();
}
}

@After
public void tearDown() throws Exception {
db.shutdown();
}

@Test
public void shouldGetRecommendation() throws IOException {
String response = service.pageRank("Person", "KNOWS", db);
assertEquals("PageRank for Person and KNOWS Completed!", response);

Map<String, Object> params = new HashMap<>();
params.put( "name", "Tom Hanks" );

Result result = db.execute(TestObjects.PERSON_PG_QUERY, params);
Iterator<Object> pageranks = result.columnAs( "p.pagerank" );
//assertEquals( 4.642800717539658, pageranks.next() );


}

}
Loading

0 comments on commit 76373c3

Please sign in to comment.