public Node getTownByName(String name) { Transaction tx = db.beginTx(); Node result2 = null; Node ss; try { ss = indexToNode(id, "geo"); // System.out.println("x22222"); // System.out.println("1111"); Traverser traverser1 = ss.traverse( Order.BREADTH_FIRST, StopEvaluator.END_OF_GRAPH, ReturnableEvaluator.ALL_BUT_START_NODE, admin_rel.PROVINCE, Direction.OUTGOING); // System.out.println("x33333"); outerloop: for (Node f : traverser1) { Traverser traverser2 = f.traverse( Order.BREADTH_FIRST, StopEvaluator.END_OF_GRAPH, ReturnableEvaluator.ALL_BUT_START_NODE, admin_rel.DISTRICT, Direction.OUTGOING); for (Node f2 : traverser2) { Traverser traverser3 = f2.traverse( Order.BREADTH_FIRST, StopEvaluator.END_OF_GRAPH, ReturnableEvaluator.ALL_BUT_START_NODE, geo_rel.PRIMARY_NODE, Direction.OUTGOING); for (Node f3 : traverser3) { if (f3.getProperty("name").equals(name)) { // System.out.println("here="+f3); // System.out.println("xxxs="+f3.getProperty("postalcode")); result2 = f3; break outerloop; } } } } tx.success(); } finally { tx.finish(); } return result2; }
@Test public void testSimpleGraph() throws Exception { GraphDatabaseService neo = dbRule.getGraphDatabaseService(); Transaction tx = neo.beginTx(); try { final Node emil = neo.createNode(); emil.setProperty("name", "Emil Eifrém"); emil.setProperty("age", 30); final Node tobias = neo.createNode(); tobias.setProperty("name", "Tobias \"thobe\" Ivarsson"); tobias.setProperty("age", 23); tobias.setProperty("hours", new int[] {10, 10, 4, 4, 0}); final Node johan = neo.createNode(); johan.setProperty("!<>)", "!<>)"); johan.setProperty("name", "!<>Johan '\\n00b' !<>Svensson"); final Relationship emilKNOWStobias = emil.createRelationshipTo(tobias, type.KNOWS); emilKNOWStobias.setProperty("since", "2003-08-17"); final Relationship johanKNOWSemil = johan.createRelationshipTo(emil, type.KNOWS); final Relationship tobiasKNOWSjohan = tobias.createRelationshipTo(johan, type.KNOWS); final Relationship tobiasWORKS_FORemil = tobias.createRelationshipTo(emil, type.WORKS_FOR); OutputStream out = new ByteArrayOutputStream(); GraphvizWriter writer = new GraphvizWriter(); writer.emit( out, Walker.crosscut( emil.traverse( Order.DEPTH_FIRST, StopEvaluator.END_OF_GRAPH, ReturnableEvaluator.ALL, type.KNOWS, Direction.BOTH, type.WORKS_FOR, Direction.BOTH), type.KNOWS, type.WORKS_FOR)); tx.success(); out.toString(); } finally { tx.finish(); } }
/** * This is an example showing a hierarchy of roles. What's interesting is that a tree is not * sufficient for storing this structure, as elaborated below. * * <p>image::roles.png[scaledwidth="100%"] * * <p>This is an implementation of an example found in the article * http://www.codeproject.com/Articles/22824/A-Model-to-Represent-Directed-Acyclic-Graphs-DAG-o[A * Model to Represent Directed Acyclic Graphs (DAG) on SQL Databases] by * http://www.codeproject.com/script/Articles/MemberArticles.aspx?amid=274518[Kemal Erdogan]. The * article discusses how to store http://en.wikipedia.org/wiki/Directed_acyclic_graph[ directed * acyclic graphs] (DAGs) in SQL based DBs. DAGs are almost trees, but with a twist: it may be * possible to reach the same node through different paths. Trees are restricted from this * possibility, which makes them much easier to handle. In our case it is "Ali" and "Engin", as * they are both admins and users and thus reachable through these group nodes. Reality often * looks this way and can't be captured by tree structures. * * <p>In the article an SQL Stored Procedure solution is provided. The main idea, that also have * some support from scientists, is to pre-calculate all possible (transitive) paths. Pros and * cons of this approach: * * <p>* decent performance on read * low performance on insert * wastes _lots_ of space * relies * on stored procedures * * <p>In Neo4j storing the roles is trivial. In this case we use +PART_OF+ (green edges) * relationships to model the group hierarchy and +MEMBER_OF+ (blue edges) to model membership in * groups. We also connect the top level groups to the reference node by +ROOT+ relationships. * This gives us a useful partitioning of the graph. Neo4j has no predefined relationship types, * you are free to create any relationship types and give them any semantics you want. * * <p>Lets now have a look at how to retrieve information from the graph. The Java code is using * the Neo4j Traversal API (see <<tutorial-traversal-java-api>>), the queries are done using * <<cypher-query-lang, Cypher>>. * * <p>== Get the admins == @@get-admins * * <p>resulting in the output @@o-get-admins * * <p>The result is collected from the traverser using this code: @@read-traverser * * <p>In Cypher, a similar query would be: @@query-get-admins * * <p>resulting in: @@o-query-get-admins * * <p>== Get the group memberships of a user == * * <p>Using the Neo4j Java Traversal API, this query looks like: @@get-user-memberships * * <p>resuling in: @@o-get-user-memberships * * <p>In Cypher: @@query-get-user-memberships @@o-query-get-user-memberships * * <p>== Get all groups == * * <p>In Java: @@get-groups * * <p>resulting in: @@o-get-groups * * <p>In Cypher: @@query-get-groups @@o-query-get-groups * * <p>== Get all members of all groups == * * <p>Now, let's try to find all users in the system being part of any group. * * <p>in Java: @@get-members @@o-get-members * * <p>In Cypher, this looks like: @@query-get-members * * <p>and results in the following output: @@o-query-get-members * * <p>As seen above, querying even more complex scenarios can be done using comparatively short * constructs in Java and other query mechanisms. */ @Test @Documented @Graph({ "Admins ROOT Reference_Node", "Users ROOT Reference_Node", "HelpDesk PART_OF Admins", "Managers PART_OF Users", "Technicians PART_OF Users", "ABCTechnicians PART_OF Technicians", "Ali MEMBER_OF Users", "Ali MEMBER_OF Admins", "Engin MEMBER_OF Users", "Engin MEMBER_OF HelpDesk", "Demet MEMBER_OF HelpDesk", "Burcu MEMBER_OF Users", "Can MEMBER_OF Users", "Gul MEMBER_OF Managers", "Fuat MEMBER_OF Managers", "Hakan MEMBER_OF Technicians", "Irmak MEMBER_OF Technicians", "Jale MEMBER_OF ABCTechnicians" }) public void user_roles_in_graphs() { // get Admins gen.get() .addTestSourceSnippets( this.getClass(), "get-admins", "get-user-memberships", "get-groups", "get-members", "read-traverser"); System.out.println("All admins:"); // START SNIPPET: get-admins Node admins = getNodeByName("Admins"); Traverser traverser = admins.traverse( Traverser.Order.BREADTH_FIRST, StopEvaluator.END_OF_GRAPH, ReturnableEvaluator.ALL_BUT_START_NODE, RoleRels.PART_OF, Direction.INCOMING, RoleRels.MEMBER_OF, Direction.INCOMING); // END SNIPPET: get-admins gen.get().addSnippet("o-get-admins", createOutputSnippet(traverserToString(traverser))); String query = "start admins=node(" + admins.getId() + ") match admins<-[:PART_OF*0..]-group<-[:MEMBER_OF]-user return user.name, group.name"; gen.get().addSnippet("query-get-admins", createCypherSnippet(query)); String result = engine.execute(query).dumpToString(); assertTrue(result.contains("Engin")); gen.get().addSnippet("o-query-get-admins", createQueryResultSnippet(result)); // Jale's memberships // START SNIPPET: get-user-memberships Node jale = getNodeByName("Jale"); traverser = jale.traverse( Traverser.Order.DEPTH_FIRST, StopEvaluator.END_OF_GRAPH, ReturnableEvaluator.ALL_BUT_START_NODE, RoleRels.MEMBER_OF, Direction.OUTGOING, RoleRels.PART_OF, Direction.OUTGOING); // END SNIPPET: get-user-memberships gen.get() .addSnippet("o-get-user-memberships", createOutputSnippet(traverserToString(traverser))); query = "start jale=node(" + jale.getId() + ") match jale-[:MEMBER_OF]->()-[:PART_OF*0..]->group return group.name"; gen.get().addSnippet("query-get-user-memberships", createCypherSnippet(query)); result = engine.execute(query).dumpToString(); assertTrue(result.contains("Users")); gen.get().addSnippet("o-query-get-user-memberships", createQueryResultSnippet(result)); // get all groups // START SNIPPET: get-groups Node referenceNode = getNodeByName("Reference_Node"); traverser = referenceNode.traverse( Traverser.Order.BREADTH_FIRST, StopEvaluator.END_OF_GRAPH, ReturnableEvaluator.ALL_BUT_START_NODE, RoleRels.ROOT, Direction.INCOMING, RoleRels.PART_OF, Direction.INCOMING); // END SNIPPET: get-groups gen.get().addSnippet("o-get-groups", createOutputSnippet(traverserToString(traverser))); query = "start refNode=node(" + referenceNode.getId() + ") match refNode<-[:ROOT]->()<-[:PART_OF*0..]-group return group.name"; gen.get().addSnippet("query-get-groups", createCypherSnippet(query)); result = engine.execute(query).dumpToString(); assertTrue(result.contains("Users")); gen.get().addSnippet("o-query-get-groups", createQueryResultSnippet(result)); // get all members // START SNIPPET: get-members traverser = referenceNode.traverse( Traverser.Order.BREADTH_FIRST, StopEvaluator.END_OF_GRAPH, new ReturnableEvaluator() { @Override public boolean isReturnableNode(TraversalPosition currentPos) { if (currentPos.isStartNode()) { return false; } Relationship rel = currentPos.lastRelationshipTraversed(); return rel.isType(RoleRels.MEMBER_OF); } }, RoleRels.ROOT, Direction.INCOMING, RoleRels.PART_OF, Direction.INCOMING, RoleRels.MEMBER_OF, Direction.INCOMING); // END SNIPPET: get-members gen.get().addSnippet("o-get-members", createOutputSnippet(traverserToString(traverser))); query = "start refNode=node(" + referenceNode.getId() + ") " + "match refNode<-[:ROOT]->root, p=root<-[PART_OF*0..]-()<-[:MEMBER_OF]-user " + "return user.name, min(length(p)) " + "order by min(length(p)), user.name"; gen.get().addSnippet("query-get-members", createCypherSnippet(query)); result = engine.execute(query).dumpToString(); assertTrue(result.contains("Engin")); gen.get().addSnippet("o-query-get-members", createQueryResultSnippet(result)); /* more advanced example query = "start refNode=node("+ referenceNode.getId() +") " + "match p=refNode<-[:ROOT]->parent<-[:PART_OF*0..]-group, group<-[:MEMBER_OF]-user return group.name, user.name, LENGTH(p) " + "order by LENGTH(p)"; */ }