Skip to content
William Lyon edited this page May 30, 2014 · 11 revisions

Week 2 05.26.14 - 06.01.14

Goals for Week 2

  • Complete implementation of intermediate Cypher function:

calculating the distance between two points? We could generalize it later to closest distance between edges of any Geometry, but let's start simple. Something like distance(a,b) where a and b are expressions that evaluate as either nodes or strings. Nodes should (in version 0.1 prototype) just contain x,y attributes. Strings should be 'POINT(x y)' WKT.

  • Finalize Spatial Cypher syntax document (?)
  • Add goals / schedule for all remaining weeks
  • Complete Week 4 and Week 5 Scala Coursera course materials (video lectures and programming assignment)

Will's Progress

As noted in the commit message, one unit test fails when Distance function is called with Node parameters (Distance returns 0.0). I believe this is caused by not properly mocking the Node objects in the test. Added to goals for next week is to figure out how to properly mock Node objects during test and resolve this error.

However, I was able to build Neo4j server after adding the Distance function and test its use in the Neo4j browser. This screenshot demonstrates 1) Creating two Nodes with x,y attributes 2) Use of distance function with these two Nodes and 3) Use of distance function with Node and WKT Point(x y) string:

There is also some (very) basic error handling in the Distance function. Initially, the only WKT format supported is POINT (x y), so display a helpful error message if not able to parse the string passed:

Scala is a new language for me, so learning Scala has been my main focus so far. One feature of Scala I found particular useful is pattern matching. Pattern matching allows for much more eloquent code. For example, the Distance function takes two arguments that evaluate to Nodes, Strings or a combination of Node and String. In this case pattern matching can be used to handle each case:

def apply(...): Any = (x, y) match {
  case (a: Node, b: Node) =>
    // logic for Node, Node
  case (a: String, b: String) =>
    // logic for String, String
  case (a: String, b: Node) =>
    // logic for String, Node
  case (a: Node, b: String) =>
    // logic for Node, String
  case (_, null) =>
    null    // evaluate to null if passed a null argument
  case (null, _) =>
    null    // evaluate to null if passed a null argument
  case (_, _) =>
    throw new CypherTypeException("distance() expected type Node, String, or a combination of Node" +
      "and String, but was called with some other type");
}

Pattern matching can also be combined with regular expressions. To parse the WKT POINT (x y) String I used something like this:


def getXYVals(s: String) (Double, Double) = {
  val WKTPointPattern = """POINT ?\(([-]?\d+\.?\d+?) ([-]?\d+\.?\d+?)\)""".r
  s match {
    case WKTPointPattern(x, y) =>
      (x.toDouble, y.toDouble)  
    case _ => throw new CypherTypeException("String parameters to distance() should be of form " +
      "POINT(x y). Call to distance() with String parameter not of this form.")
  }
}

So far I am very impressed with Scala and look forward to using it more!