forked from maxdemarzi/graph_processing
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ad73c3a
commit 76373c3
Showing
6 changed files
with
828 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
*.iml | ||
.idea | ||
target | ||
neo4j |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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!"; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() ); | ||
|
||
|
||
} | ||
|
||
} |
Oops, something went wrong.