Permalink
Browse files

hand crafting GraphViz graphs to illustrate the PathTree

  • Loading branch information...
1 parent b29797b commit 6c87de5136b78affaf7a4cc62ea9e26e2bda47c4 @peterneubauer peterneubauer committed Feb 17, 2012
@@ -88,9 +88,11 @@ The structure follows a couple of rules:
- The querying is done in a path-range fashion. That is, the start- and end path from the indexing root to the start and end leafs in the tree are calculated
- Using Cypher, the queries following different strategies can be expressed as path sections and put together using one single query.
+The graph below depicts a structure with 3 Events being attached to an index structure at different leafs.
+
:leveloffset: 2
-include::cypher-pathtree-graph.txt[]
+include::path-tree-layout.txt[]
include::return-zero-range.txt[]
@@ -0,0 +1,49 @@
+
+_Graph_
+
+["dot", "cypher-pathtree-layout-full-range-path.svg", "neoviz"]
+----
+ root [label="Root"]
+
+ subgraph years {
+ Y10 [label="Year 2010"]
+ Y11 [label="Year 2011"]
+ root -> Y10 [label="2010", penwidth=3,color=greenyellow]
+ root -> Y11 [label="2011", penwidth=3,color=darkgreen]
+
+ }
+ subgraph months {
+ Y10M12 [label="Month 12"]
+ Y11M01 [label="Month 01"]
+ Y10 -> Y10M12 [label="12", penwidth=3, color=greenyellow]
+ Y11 -> Y11M01 [label="01", penwidth=3, color=darkgreen]
+ }
+ subgraph days {
+ Y10M12D31 [label="Day 31"]
+ Y11M01D01 [label="Day 01"]
+ Y11M01D02 [label="Day 02"]
+ Y11M01D03 [label="Day 03"]
+ Y10M12 -> Y10M12D31 [label="31", penwidth=3, color=greenyellow]
+ Y11M01 -> Y11M01D01 [label="01"]
+ Y11M01 -> Y11M01D02 [label="02"]
+ Y11M01 -> Y11M01D03 [label="03", penwidth=3, color=darkgreen]
+ Y10M12D31 -> Y11M01D01 [label="NEXT", penwidth=3, color=blue]
+ Y11M01D01 -> Y11M01D02 [label="NEXT", penwidth=3, color=blue]
+ Y11M01D02 -> Y11M01D03 [label="NEXT", penwidth=3, color=blue]
+
+ }
+ subgraph events {
+ node [penwidth=2]
+ E1 [label="Event1"]
+ E2 [label="Event2"]
+ E3 [label="Event3"]
+ Y10M12D31 -> E1 [label="VALUE", penwidth=3, color=red]
+ Y10M12D31 -> E2 [label="VALUE", penwidth=3, color=red]
+ Y11M01D01 -> E2 [label="VALUE", penwidth=3, color=red]
+ Y11M01D03 -> E3 [label="VALUE", penwidth=3, color=red]
+ }
+ {rank=same; "E1" "E2" "E3"}
+ {rank=same; "Y10M12D31" "Y11M01D01" "Y11M01D02" "Y11M01D03"}
+ {rank=same; "E1" "E2" "E3"}
+
+----
@@ -0,0 +1,49 @@
+
+_Graph_
+
+["dot", "cypher-pathtree-layout-shared-root-path.svg", "neoviz"]
+----
+ root [label="Root"]
+
+ subgraph years {
+ Y10 [label="Year 2010"]
+ Y11 [label="Year 2011"]
+ root -> Y10 [label="2010",]
+ root -> Y11 [label="2011", penwidth=3,color=black]
+
+ }
+ subgraph months {
+ Y10M12 [label="Month 12"]
+ Y11M01 [label="Month 01"]
+ Y10 -> Y10M12 [label="12"]
+ Y11 -> Y11M01 [label="01", penwidth=3, color=black]
+ }
+ subgraph days {
+ Y10M12D31 [label="Day 31"]
+ Y11M01D01 [label="Day 01"]
+ Y11M01D02 [label="Day 02"]
+ Y11M01D03 [label="Day 03"]
+ Y10M12 -> Y10M12D31 [label="31"]
+ Y11M01 -> Y11M01D01 [label="01", penwidth=3, color=greenyellow]
+ Y11M01 -> Y11M01D02 [label="02"]
+ Y11M01 -> Y11M01D03 [label="03", penwidth=3, color=darkgreen]
+ Y10M12D31 -> Y11M01D01 [label="NEXT"]
+ Y11M01D01 -> Y11M01D02 [label="NEXT", penwidth=3, color=blue]
+ Y11M01D02 -> Y11M01D03 [label="NEXT", penwidth=3, color=blue]
+
+ }
+ subgraph events {
+ node [penwidth=2]
+ E1 [label="Event1"]
+ E2 [label="Event2"]
+ E3 [label="Event3"]
+ Y10M12D31 -> E1 [label="VALUE"]
+ Y10M12D31 -> E2 [label="VALUE"]
+ Y11M01D01 -> E2 [label="VALUE", penwidth=3, color=red]
+ Y11M01D03 -> E3 [label="VALUE", penwidth=3, color=red]
+ }
+ {rank=same; "E1" "E2" "E3"}
+ {rank=same; "Y10M12D31" "Y11M01D01" "Y11M01D02" "Y11M01D03"}
+ {rank=same; "E1" "E2" "E3"}
+
+----
@@ -0,0 +1,49 @@
+
+_Graph_
+
+["dot", "cypher-pathtree-layout-zero-range.svg", "neoviz"]
+----
+ root [label="Root"]
+
+ subgraph years {
+ Y10 [label="Year 2010"]
+ Y11 [label="Year 2011"]
+ root -> Y10 [label="2010",penwidth=3,color=green]
+ root -> Y11 [label="2011"]
+
+ }
+ subgraph months {
+ Y10M12 [label="Month 12"]
+ Y11M01 [label="Month 01"]
+ Y10 -> Y10M12 [label="12", penwidth=3,color=green]
+ Y11 -> Y11M01 [label="01"]
+ }
+ subgraph days {
+ Y10M12D31 [label="Day 31"]
+ Y11M01D01 [label="Day 01"]
+ Y11M01D02 [label="Day 02"]
+ Y11M01D03 [label="Day 03"]
+ Y10M12 -> Y10M12D31 [label="31", penwidth=3,color=green]
+ Y11M01 -> Y11M01D01 [label="01"]
+ Y11M01 -> Y11M01D02 [label="02"]
+ Y11M01 -> Y11M01D03 [label="03"]
+ Y10M12D31 -> Y11M01D01 [label="NEXT"]
+ Y11M01D01 -> Y11M01D02 [label="NEXT"]
+ Y11M01D02 -> Y11M01D03 [label="NEXT"]
+
+ }
+ subgraph events {
+ node [penwidth=2]
+ E1 [label="Event1"]
+ E2 [label="Event2"]
+ E3 [label="Event3"]
+ Y10M12D31 -> E1 [label="VALUE", penwidth=3, color=red]
+ Y10M12D31 -> E2 [label="VALUE", penwidth=3, color=red]
+ Y11M01D01 -> E2 [label="VALUE"]
+ Y11M01D03 -> E3 [label="VALUE"]
+ }
+ {rank=same; "E1" "E2" "E3"}
+ {rank=same; "Y10M12D31" "Y11M01D01" "Y11M01D02" "Y11M01D03"}
+ {rank=same; "E1" "E2" "E3"}
+
+----
@@ -0,0 +1,49 @@
+
+_Graph_
+
+["dot", "cypher-pathtree-layout-path.svg", "neoviz"]
+----
+ root [label="Root"]
+
+ subgraph years {
+ Y10 [label="Year 2010"]
+ Y11 [label="Year 2011"]
+ root -> Y10 [label="2010",]
+ root -> Y11 [label="2011"]
+
+ }
+ subgraph months {
+ Y10M12 [label="Month 12"]
+ Y11M01 [label="Month 01"]
+ Y10 -> Y10M12 [label="12"]
+ Y11 -> Y11M01 [label="01"]
+ }
+ subgraph days {
+ Y10M12D31 [label="Day 31"]
+ Y11M01D01 [label="Day 01"]
+ Y11M01D02 [label="Day 02"]
+ Y11M01D03 [label="Day 03"]
+ Y10M12 -> Y10M12D31 [label="31"]
+ Y11M01 -> Y11M01D01 [label="01"]
+ Y11M01 -> Y11M01D02 [label="02"]
+ Y11M01 -> Y11M01D03 [label="03"]
+ Y10M12D31 -> Y11M01D01 [label="NEXT"]
+ Y11M01D01 -> Y11M01D02 [label="NEXT"]
+ Y11M01D02 -> Y11M01D03 [label="NEXT"]
+
+ }
+ subgraph events {
+ node [penwidth=2]
+ E1 [label="Event1"]
+ E2 [label="Event2"]
+ E3 [label="Event3"]
+ Y10M12D31 -> E1 [label="VALUE"]
+ Y10M12D31 -> E2 [label="VALUE"]
+ Y11M01D01 -> E2 [label="VALUE"]
+ Y11M01D03 -> E3 [label="VALUE"]
+ }
+ {rank=same; "E1" "E2" "E3"}
+ {rank=same; "Y10M12D31" "Y11M01D01" "Y11M01D02" "Y11M01D03"}
+ {rank=same; "E1" "E2" "E3"}
+
+----
@@ -28,37 +28,41 @@ class PathTreeTest extends DocumentingTestBase {
def graphDescription = List(
"Root 2010 Y10",
"Root 2011 Y11",
- "Y10 NEXT Y11",
"Y10 12 Y10M12",
- "Y11 12 Y11M12",
- "Y10M12 NEXT Y11M12",
- "Y10M12 25 Y10M12D25",
- "Y11M12 25 Y11M12D25",
- "Y11M12 30 Y11M12D30",
- "Y10M12D25 NEXT Y11M12D25",
- "Y11M12D25 NEXT Y11M12D30",
- "Y10M12D25 VALUE Event1",
- "Y10M12D25 VALUE Event2",
- "Y11M12D25 VALUE Event2",
- "Y11M12D30 VALUE Event3")
+ "Y11 01 Y11M01",
+ "Y10M12 31 Y10M12D31",
+ "Y11M01 01 Y11M01D01",
+ "Y11M01 02 Y11M11D02",
+ "Y11M01 03 Y11M12D03",
+ "Y10M12D31 NEXT Y11M01D01",
+ "Y11M01D01 NEXT Y11M11D02",
+ "Y11M11D02 NEXT Y11M12D03",
+ "Y10M12D31 VALUE Event1",
+ "Y10M12D31 VALUE Event2",
+ "Y11M01D01 VALUE Event2",
+ "Y11M12D03 VALUE Event3")
def section = "cookbook"
@Test def allEvents() {
testQuery(
title = "Return the full range",
text = """In this case, the range goes from the first to the last leaf of the index tree. Here,
- +startPath+ and +endPath+ span up the range, +valuePath+ is then connecting the leafs, and the values can
- be read from teh +middle+ node.""",
+ +startPath+ (color +Greenyellow+) and +endPath+ (color +Green+) span up the range, +valuePath+ (color +Blue+) is then connecting the leafs, and the values canan
+ be read from the +middle+ node, hanging off the +values+ (color +Red+) path.
+
+include::path-tree-layout-full-range.txt[]
+
+ """,
queryText = "START root=node:node_auto_index(name = 'Root') " +
"MATCH " +
- "startPath=root-[:`2010`]->()-[:`12`]->()-[:`25`]->startLeaf, " +
- "endPath=root-[`:2011`]->()-[:`12`]->()-[:`30`]->endLeaf, " +
+ "startPath=root-[:`2010`]->()-[:`12`]->()-[:`31`]->startLeaf, " +
+ "endPath=root-[`:2011`]->()-[:`01`]->()-[:`03`]->endLeaf, " +
"valuePath=startLeaf-[:NEXT*0..]->middle-[:NEXT*0..]->endLeaf, " +
- "middle-[:VALUE]->event " +
+ "values=middle-[:VALUE]->event " +
"RETURN event.name " +
"ORDER BY event.name ASC",
- returns = "Returning all events between 2010-12-25 and 2011-12-30, in this case all events.",
+ returns = "Returning all events between 2010-12-31 and 2011-01-03, in this case all events.",
(p) => assertEquals(List(Map("event.name" -> "Event1"),
Map("event.name" -> "Event2"),
Map("event.name" -> "Event2"),
@@ -68,15 +72,19 @@ class PathTreeTest extends DocumentingTestBase {
@Test def singleDate() {
testQuery(
title = "Return zero range",
- text = """Here, only the events indexed with on the same leaf (2010-12-25) are returned.
- The query only needs one path segment (+rootPath+) through the index.""",
+ text = """Here, only the events indexed under one leaf (2010-12-31) are returned.
+ The query only needs one path segment +rootPath+ (color +Green+) through the index.
+
+include::path-tree-layout-zero-range.txt[]
+
+ """,
queryText = "START root=node:node_auto_index(name = 'Root') " +
"MATCH " +
- "rootPath=root-[:`2010`]->()-[:`12`]->()-[:`25`]->leaf, " +
+ "rootPath=root-[:`2010`]->()-[:`12`]->()-[:`31`]->leaf, " +
"leaf-[:VALUE]->event " +
"RETURN event.name " +
"ORDER BY event.name ASC",
- returns = "Returning all events on the date 2010-12-25, in this case +Event1+ and +Event2+",
+ returns = "Returning all events on the date 2010-12-31, in this case +Event1+ and +Event2+",
(p) => assertEquals(List(Map("event.name" -> "Event1"),
Map("event.name" -> "Event2")
),p.toList))
@@ -86,18 +94,22 @@ class PathTreeTest extends DocumentingTestBase {
testQuery(
title = "Return partly shared path ranges",
text = """Here, the query range results in partly shared paths when querying the index,
- making the introduction of and common path segment +commonPath+ necessary, before spanning up +startPath+ and
- +endPath+. After that, +valuePath+ connects the leafs and the indexed values are returned off +middle+.""",
+making the introduction of and common path segment +commonPath+ (color +Black+) necessary, before spanning up +startPath+ (color +Greenyellow+) and
++endPath+ (color +Darkgreen+) . After that, +valuePath+ (color +Blue+) connects the leafs and the indexed values are returned off +values+ (color +Red+) path.
+
+include::path-tree-layout-shared-root-path.txt[]
+
+ """,
queryText = "START root=node:node_auto_index(name = 'Root') " +
"MATCH " +
- "commonPath=root-[:`2011`]->()-[:`12`]->commonRootEnd, " +
- "startPath=commonRootEnd-[:`25`]->startLeaf, " +
- "endPath=commonRootEnd-[:`30`]->endLeaf, " +
+ "commonPath=root-[:`2011`]->()-[:`01`]->commonRootEnd, " +
+ "startPath=commonRootEnd-[:`01`]->startLeaf, " +
+ "endPath=commonRootEnd-[:`03`]->endLeaf, " +
"valuePath=startLeaf-[:NEXT*0..]->middle-[:NEXT*0..]->endLeaf, " +
- "middle-[:VALUE]->event " +
+ "values=middle-[:VALUE]->event " +
"RETURN event.name " +
"ORDER BY event.name ASC",
- returns = "Returning all events between 2011-12-25 and 2011-12-30, in this case +Event2+ and +Event3+.",
+ returns = "Returning all events between 2011-01-01 and 2011-01-03, in this case +Event2+ and +Event3+.",
(p) => assertEquals(List(
Map("event.name" -> "Event2"),
Map("event.name" -> "Event3")
@@ -94,7 +94,8 @@ public static String createCypherSnippet( final String query )
{
String upperKeyword = keyword.toUpperCase();
result = result.
- replace(keyword, upperKeyword).
+ replace(keyword+" ", upperKeyword+" ").
+ replace(keyword+" ", upperKeyword+" ").
replace(" " + upperKeyword + " ", "\n" + upperKeyword + " ");
}

0 comments on commit 6c87de5

Please sign in to comment.