Permalink
Browse files

Added cook book examples - pretty graphs and linked list

  • Loading branch information...
1 parent ce33b92 commit 1902ca0019dd74ce9446fbdcb45883b89d0b5c28 @peterneubauer peterneubauer committed with May 28, 2012
@@ -96,6 +96,53 @@ include::who-follows-or-loves-me-back.txt[]
:leveloffset: 1
+[[cypher-cookbook-pretty-graphs]]
+== Pretty graphs in Cypher ==
+
+This section is showing how to create some of the http://en.wikipedia.org/wiki/Gallery_of_named_graphs[named pretty graphs on Wikipedia].
+
+The graph visualizations look best using a Force Directed Layout, while the current layout below is different. For better results,
+use the live demos in http://docs.neo4j.org[the online version of this manual].
+
+:leveloffset: 2
+
+include::star-graph.txt[]
+
+include::cypher-prettygraphsstar-graph.txt[]
+
+:leveloffset: 2
+
+include::wheel-graph.txt[]
+
+include::cypher-prettygraphswheel-graph.txt[]
+
+:leveloffset: 2
+
+include::complete-graph.txt[]
+
+include::cypher-prettygraphscompletegraph-graph.txt[]
+
+:leveloffset: 2
+
+include::friendship-graph.txt[]
+
+include::cypher-prettygraphsfriendshipgraph-graph.txt[]
+
+:leveloffset: 1
+
+[[cypher-cookbook-complex-updates]]
+== Complex updates ==
+
+This section is showing some graph-related update operations that require advanced graph manipulations.
+
+:leveloffset: 2
+
+include::insert-a-new-value-into-a-linked-list.txt[]
+
+include::cypher-linkedlist-graph.txt[]
+
+:leveloffset: 1
+
[[cypher-cookbook-path-tree]]
== A multilevel indexing structure (path tree) ==
@@ -122,7 +169,18 @@ include::return-the-full-range.txt[]
include::return-partly-shared-path-ranges.txt[]
-//:leveloffset: 1
+:leveloffset: 1
+
+[[cypher-cookbook-similarity-calc]]
+== More complex similarity computations ==
+
+:leveloffset: 2
+
+include::calculate-similarities-by-complex-calculations.txt[]
+
+include::cypher-complexsimilarity-graph.txt[]
+
+
//== Activity Streams ==
@@ -112,6 +112,12 @@ _Graph_
graphViz.close()
}
+ def executeQuery(queryText: String): ExecutionResult = {
+ var query = queryText
+ nodes.keySet.foreach((key) => query = query.replace("%" + key + "%", node(key).getId.toString))
+ engine.execute(query)
+ }
+
def testQuery(title: String, text: String, queryText: String, returns: String, assertions: (ExecutionResult => Unit)*) {
val r = testWithoutDocs(queryText, assertions:_*)
val result: ExecutionResult = r._1
@@ -0,0 +1,46 @@
+/**
+ * Copyright (c) 2002-2012 "Neo Technology,"
+ * Network Engine for Objects in Lund AB [http://neotechnology.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.neo4j.cypher.docgen.cookbook
+
+import org.junit.Test
+import org.junit.Assert._
+import org.neo4j.cypher.docgen.DocumentingTestBase
+import org.junit.Ignore
+
+class ComplexSimilarityTest extends DocumentingTestBase {
+ def graphDescription = List()
+ def section = "cookbook"
+
+ @Test def testSimliarity() {
+ executeQuery("CREATE (me {name:'me'})-[:ATE {times:10}]->(food {name:'meat'})<-[:ATE {times:5}]-(you {name:'you'})")
+ testQuery(
+ title = "Calculate similarities by complex calculations",
+ text =
+"""Here, a similarity between two players in a game is calculated by the number of times they have eaten the same food.""",
+ queryText = """START me=node(*)
+MATCH me-[r1:ATE]->food<-[r2:ATE]-you
+WHERE has(me.name) and me.name = 'me'
+==== me,count(distinct r1) as H1,count(distinct r2) as H2,you ====
+MATCH me-[r1:ATE]->food<-[r2:ATE]-you
+RETURN sum((1-ABS(r1.times/H1-r2.times/H2))*(r1.times+r2.times)/(H1+H2)) as similarity""",
+ returns = "The two players and their similarity measure.",
+ assertions = (p) => assertEquals(List(Map("similarity" -> -30.0)),p.toList))
+ }
+}
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 2002-2012 "Neo Technology,"
+ * Network Engine for Objects in Lund AB [http://neotechnology.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.neo4j.cypher.docgen.cookbook
+
+import org.junit.Test
+import org.junit.Assert._
+import org.neo4j.cypher.docgen.DocumentingTestBase
+
+class LinkedListTest extends DocumentingTestBase {
+ def graphDescription = List()
+ def section = "cookbook"
+
+ @Test def completeGraph() {
+ testQuery(
+ title = "Insert a new value into a linked list",
+ text =
+"""In this example, a new value is inserted at the right position into an existing Linked List.
+
+Firstly, a new linked list, containing the nodes with values `0` and `2` is created in the first
+subquery.
+
+In the second part, we are looking for the node in the position before our new node will have, and the node that will come after.
+They will already be connected with each other with the relationship identifier `old`.
+The 0 in `zero-[:LINK*0..]->before` means that there are zero or more relationships between
+the root node and the before node. Having zero relationships between two node in a path means that they are the same
+node. When the linked list is empty, the `root`, `before` and `after` identifier will all point to the same node -
+ the newly created root node. The self relationship will be in the `old` identifier.
+
+In the last query part, the `old` relationship is deleted.""",
+ queryText = """CREATE zero={name:0,value:0}, two={value:2,name:2}, zero-[:LINK]->two-[:LINK]->zero
+==== zero ====
+MATCH zero-[:LINK*0..]->before,
+ after-[:LINK*0..]->zero,
+ before-[old:LINK]->after
+WHERE before.value? <= 1 AND
+ 1 <= after.value?
+CREATE newValue={name:1,value : 1},
+ before-[:LINK]->newValue,
+ newValue-[:LINK]->after
+DELETE old
+==== zero ====
+MATCH p = zero-[:LINK*1..]->zero
+RETURN length(p) as list_length""",
+ returns =
+"""The length of the full list.""",
+ assertions = (p) => assertEquals(List(Map("list_length" -> 3)),p.toList))
+ }
+}
@@ -0,0 +1,54 @@
+/**
+ * Copyright (c) 2002-2012 "Neo Technology,"
+ * Network Engine for Objects in Lund AB [http://neotechnology.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.neo4j.cypher.docgen.cookbook
+
+import org.junit.Test
+import org.junit.Assert._
+import org.neo4j.cypher.docgen.DocumentingTestBase
+
+class PrettyGraphsCompleteGraphTest extends DocumentingTestBase {
+ def graphDescription = List()
+ def section = "cookbook"
+
+ @Test def completeGraph() {
+ testQuery(
+ title = "Complete graph",
+ text =
+"""For this graph, a root node is created, and used to hang a number
+ of nodes from. Then, two nodes are selected, hanging from the center, with the requirement that the
+ id of the first be less than the id of the next. This is to prevent double relationships and
+ self relationships. Using said match, relationships between all these nodes are created. Lastly,
+ the center node and all relationships connected to it are removed.""",
+ queryText = """create center
+foreach( x in range(1,10) :
+ create leaf={count : x}, center-[:X]->leaf
+)
+==== center ====
+MATCH leaf1<--center-->leaf2
+WHERE id(leaf1)<id(leaf2)
+CREATE leaf1-[:X]->leaf2
+==== center ====
+MATCH center-[r]->()
+DELETE center,r;""",
+ returns =
+"""Nothing returned.""",
+ assertions = (p) => assertTrue(true))
+ }
+}
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2002-2012 "Neo Technology,"
+ * Network Engine for Objects in Lund AB [http://neotechnology.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.neo4j.cypher.docgen.cookbook
+
+import org.junit.Test
+import org.junit.Assert._
+import org.neo4j.cypher.docgen.DocumentingTestBase
+
+class PrettyGraphsFriendshipGraphTest extends DocumentingTestBase {
+ def graphDescription = List()
+ def section = "cookbook"
+
+ @Test def completeGraph() {
+ testQuery(
+ title = "Friendship graph",
+ text =
+"""Works by first creating a center node, and then once per element in the range, creates a cycle graph and connects it to the center""",
+ queryText = """CREATE center
+foreach( x in range(1,10) :
+ CREATE leaf1, leaf2, center-[:X]->leaf1, center-[:X]->leaf2, leaf1-[:X]->leaf2
+)
+RETURN ID(center) as id""",
+ returns =
+"""The id of the center node.""",
+ assertions = (p) => assertEquals(List(Map("id" -> 1)),p.toList))
+ }
+}
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2002-2012 "Neo Technology,"
+ * Network Engine for Objects in Lund AB [http://neotechnology.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.neo4j.cypher.docgen.cookbook
+
+import org.junit.Test
+import org.junit.Assert._
+import org.neo4j.cypher.docgen.DocumentingTestBase
+
+class PrettyGraphsStarTest extends DocumentingTestBase {
+ def graphDescription = List()
+ def section = "cookbook"
+
+ @Test def completeGraph() {
+ testQuery(
+ title = "Star graph",
+ text =
+"""Works by first creating a center node, and then once per element in the range, creates a leaf node and connects it to the center""",
+ queryText = """create center
+foreach( x in range(1,10) :
+ create leaf, center-[:X]->leaf
+)
+return id(center) as id;""",
+ returns =
+"""The center node.""",
+ assertions = (p) => assertEquals(List(Map("id" -> 1)),p.toList))
+ }
+}
Oops, something went wrong.

0 comments on commit 1902ca0

Please sign in to comment.