Last active
December 28, 2015 13:19
-
-
Save jexp/7506922 to your computer and use it in GitHub Desktop.
Example for loading the first n-elements of a Activity Stream with an unmanaged Neo4j-Server-Extension
This file contains hidden or 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
| package org.neo4j.example.activity; | |
| import org.codehaus.jackson.map.ObjectMapper; | |
| import org.neo4j.graphdb.GraphDatabaseService; | |
| import javax.ws.rs.*; | |
| import javax.ws.rs.core.*; | |
| import java.io.IOException; | |
| import java.io.OutputStream; | |
| @Path("/activities") | |
| public class ActivityResource { | |
| private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); | |
| private final ActivityStream stream; | |
| public ActivityResource(@Context GraphDatabaseService db, @Context UriInfo uriInfo) { | |
| stream = new ActivityStream(db); | |
| } | |
| @GET | |
| @Produces(MediaType.APPLICATION_JSON) | |
| @Path("/{userName}") | |
| public Response getActivityStream(@PathParam("userName") final String userName, | |
| @QueryParam("count") final Integer count) { | |
| return Response.ok().entity(new StreamingOutput() { | |
| public void write(OutputStream out) throws IOException, WebApplicationException { | |
| OBJECT_MAPPER.writeValue(out, stream.loadStream(userName,count)); | |
| } | |
| }).build(); | |
| } | |
| } |
This file contains hidden or 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
| MATCH (head:ActivityHead)-[:NEXT*]->(activity)-[:IN_FORUM]-> | |
| (forum:Forum)<-[:FOLLOWS]-(user:User {name: {name}}), | |
| (activity)<-[:WROTE]-(author:User) | |
| RETURN author.name, activity.message, forum.name | |
| LIMIT 20 |
This file contains hidden or 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
| package org.neo4j.example.activity; | |
| import org.neo4j.graphdb.*; | |
| import org.neo4j.tooling.GlobalGraphOperations; | |
| import java.util.*; | |
| import static org.neo4j.example.activity.ActivityStream.Labels.*; | |
| import static org.neo4j.example.activity.ActivityStream.Relationships.*; | |
| import static org.neo4j.graphdb.Direction.*; | |
| import static org.neo4j.helpers.collection.IteratorUtil.single; | |
| public class ActivityStream { | |
| public static final String NAME = "name"; | |
| public static final String MESSAGE = "message"; | |
| enum Labels implements Label { | |
| User, Forum, Activity, ActivityHead | |
| } | |
| enum Relationships implements RelationshipType { | |
| FOLLOWS,NEXT, WROTE, IN_FORUM | |
| } | |
| private final GraphDatabaseService gdb; | |
| public ActivityStream(GraphDatabaseService gdb) { | |
| this.gdb = gdb; | |
| } | |
| static class Activity { | |
| public final String author; | |
| public final String message; | |
| public final String forum; | |
| Activity(String author, String message, String forum) { | |
| this.author = author; | |
| this.message = message; | |
| this.forum = forum; | |
| } | |
| public static Activity from(Node node, Node forum) { | |
| Node author = node.getSingleRelationship(WROTE, INCOMING).getEndNode(); | |
| return new Activity((String)author.getProperty(NAME), | |
| (String)node.getProperty(MESSAGE), | |
| (String)forum.getProperty(NAME)); | |
| } | |
| } | |
| public List<Activity> loadStream(String name, int count) { | |
| try (Transaction tx = gdb.beginTx()) { | |
| Node user = single(gdb.findNodesByLabelAndProperty(User, NAME, name)); | |
| Set<Node> forums = loadForums(user); | |
| List<Activity> activities = loadActivities(count, forums); | |
| tx.success(); | |
| return activities; | |
| } | |
| } | |
| private List<Activity> loadActivities(int count, Set<Node> forums) { | |
| List<Activity> activities = new ArrayList<>(count); | |
| Node activity = single(GlobalGraphOperations.at(gdb).getAllNodesWithLabel(ActivityHead)); | |
| while (activity != null && activities.size() < count) { | |
| Node forum = activity.getSingleRelationship(IN_FORUM, OUTGOING).getEndNode(); | |
| if (forums.contains(forum)) { | |
| activities.add(ActivityStream.Activity.from(activity,forum)); | |
| } | |
| activity = activity.hasRelationship(NEXT, OUTGOING) ? | |
| activity.getSingleRelationship(NEXT, OUTGOING).getEndNode() : null; | |
| } | |
| return activities; | |
| } | |
| private Set<Node> loadForums(Node user) { | |
| Set<Node> forums=new HashSet<>(); | |
| for (Relationship follows : user.getRelationships(OUTGOING, FOLLOWS)) { | |
| forums.add(follows.getEndNode()); | |
| } | |
| return forums; | |
| } | |
| } |
This file contains hidden or 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
| package org.neo4j.example.activity; | |
| import org.junit.After; | |
| import org.junit.Before; | |
| import org.junit.Test; | |
| import org.neo4j.graphdb.GraphDatabaseService; | |
| import org.neo4j.graphdb.Node; | |
| import org.neo4j.graphdb.Transaction; | |
| import org.neo4j.test.TestGraphDatabaseFactory; | |
| import java.util.List; | |
| import static org.junit.Assert.assertEquals; | |
| import static org.neo4j.example.activity.ActivityStream.Labels.Activity; | |
| import static org.neo4j.example.activity.ActivityStream.Labels.Forum; | |
| import static org.neo4j.example.activity.ActivityStream.Labels.User; | |
| import static org.neo4j.example.activity.ActivityStream.MESSAGE; | |
| import static org.neo4j.example.activity.ActivityStream.NAME; | |
| import static org.neo4j.example.activity.ActivityStream.Relationships.*; | |
| /** | |
| * @author mh | |
| * @since 17.11.13 | |
| */ | |
| public class ActivityStreamTest { | |
| public static final String GRAPH_REFACTORING = "Graph Refactoring"; | |
| public static final String GRAPH_USE_CASES = "Graph Use Cases"; | |
| public static final String CAP_VS_ACID = "CAP vs ACID"; | |
| public static final String PETER = "Peter"; | |
| public static final String GRAPHS = "Graphs"; | |
| public static final String IAN = "Ian"; | |
| public static final String MICHAEL = "Michael"; | |
| public static final String NO_SQL = "NoSQL"; | |
| private GraphDatabaseService db; | |
| private ActivityStream activityStream; | |
| private Transaction tx; | |
| @Before | |
| public void setUp() throws Exception { | |
| db = new TestGraphDatabaseFactory().newImpermanentDatabase(); | |
| activityStream = new ActivityStream(db); | |
| tx = db.beginTx(); | |
| } | |
| @After | |
| public void tearDown() throws Exception { | |
| tx.close(); | |
| db.shutdown(); | |
| } | |
| @Test | |
| public void testLoadSingleItem() throws Exception { | |
| createTestData(); | |
| List<ActivityStream.Activity> activities = activityStream.loadStream(MICHAEL, 1); | |
| assertEquals(1,activities.size()); | |
| assertEquals(CAP_VS_ACID,activities.get(0).message); | |
| } | |
| @Test | |
| public void testLoadFullStream() throws Exception { | |
| createTestData(); | |
| List<ActivityStream.Activity> activities = activityStream.loadStream(MICHAEL, 10); | |
| assertEquals(3,activities.size()); | |
| assertEquals(CAP_VS_ACID,activities.get(0).message); | |
| assertEquals(GRAPH_USE_CASES,activities.get(1).message); | |
| assertEquals(GRAPH_REFACTORING,activities.get(2).message); | |
| } | |
| @Test | |
| public void testLoadItemsForSingleForum() throws Exception { | |
| createTestData(); | |
| List<ActivityStream.Activity> activities = activityStream.loadStream(IAN, 5); | |
| assertEquals(2,activities.size()); | |
| assertEquals(GRAPH_USE_CASES,activities.get(0).message); | |
| assertEquals(PETER,activities.get(0).author); | |
| assertEquals(GRAPHS,activities.get(0).forum); | |
| assertEquals(GRAPH_REFACTORING,activities.get(1).message); | |
| assertEquals(IAN,activities.get(1).author); | |
| } | |
| private void createTestData() { | |
| Node michael = createUser(MICHAEL); | |
| Node peter = createUser(PETER); | |
| Node ian = createUser(IAN); | |
| Node noSQL = createForum(NO_SQL,michael,peter); | |
| Node graphs = createForum(GRAPHS,michael,ian,peter); | |
| Node message1 = createMessage(GRAPH_REFACTORING, ian, graphs, null); | |
| Node message2 = createMessage(GRAPH_USE_CASES, peter, graphs, message1); | |
| Node message3 = createMessage(CAP_VS_ACID, peter, noSQL, message2); | |
| message3.addLabel(ActivityStream.Labels.ActivityHead); | |
| } | |
| private Node createUser(String name) { | |
| Node user = db.createNode(User); | |
| user.setProperty(NAME, name); | |
| return user; | |
| } | |
| private Node createForum(String name,Node...followers) { | |
| Node forum = db.createNode(Forum); | |
| forum.setProperty(NAME, name); | |
| for (Node follower : followers) { | |
| follower.createRelationshipTo(forum, FOLLOWS); | |
| } | |
| return forum; | |
| } | |
| private Node createMessage(String message, Node author,Node forum,Node previous) { | |
| Node activity = db.createNode(Activity); | |
| activity.setProperty(MESSAGE, message); | |
| author.createRelationshipTo(activity, WROTE); | |
| activity.createRelationshipTo(forum, IN_FORUM); | |
| if (previous!=null) activity.createRelationshipTo(previous, NEXT); | |
| return activity; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment