/akka-http-neo4j

Neo4j Scala library for use with akka-http

Primary LanguageScalaApache License 2.0Apache-2.0

akka-http-neo4j

Neo4j Scala library for use with akka-http and spray-json

Build Status

This library supports Cypher asynchronous queries to the Neo4j Database. It provides several shorthands and useful abstractions for interacting with Neo4j. It relies on akka-http to perform queries to the Neo4j REST API.

spray-json is not required, but to enjoy the full benefits of the library - it is recommended.

Examples

There are three default clients:

  • StringClient - returns the HTML response body as is
  • JsonClient - parses the HTML body to JSON
  • ObjectClient - parse the HTML body to rows on the form Stream[Map[String, JsValue]]

Performing queries

import akka.http.neo4j._

val query  = """CREATE (m:Message {text: "Hello, world!"}) RETURN m""".n4jQuery
val client = Neo4jClients.objectClient()

client send query
// returns: Future[N4jResponse]

As you can see, String has the convenience method .n4jQuery which turns the string into an N4jQuery acceptable by the client's send method.

Parsing result

The future returned by the client is in fact an Either. Either an N4jError or an N4jRows is returned. The latter is just a type alias for Stream[Map[String,JsValue]].

val req = client send query // using same values as the above example

req map {
  case Right(rows) => rows foreach println // prints: Map(m -> {text:"Hello, world!"})
  case Left(err)   => println(s"${err.code} ${err.message}")
}

Case Classes

Case classes can both be read from and to the database given that the case class has a JsonFormat[T]. This is easily achievable:

case class Foo(title: String, desc: String)
implicit val formatFoo = jsonFormat2(Foo.apply)

This case class can now be turned into a CQL node.

Writing to DB

Foo("Title!", "Description!").toCQLNode("n")
// returns: (n:Foo {title:"Title!",desc:"Description!"})

The case class can now be inserted into a query:

val fooNode = Foo("Title!", "Description!").toCQLNode("n")

val insert = s"""CREATE $fooNode RETURN n""".n4jQuery

Prepared statements

akka-http-neo4j uses prepared statements in the same way that the REST API for Neo4j does. In the query string, values wrapped in curly braces will be regarded as placeholders. Use the on method on the N4jQuery object to create a prepared statement.

val query = "CREATE (n {props}) RETURN n"
  .n4jQuery
  .on("props" -> Map("name" -> "My Node"))

client send query

Parsing case classes from DB

(client send insert) map {
  case Right(rows) => rows map { _.read[Foo]("n") }
  case _ => Stream.empty
}
// returns Stream[Foo]

This will give you DeserializationException (spray-json) if unsuccessful. As such, any calls that might fail should use the readOpt[T] method:

(client send insert) map {
  case Right(rows) => rows.map( _.readOpt[Foo]("n") ).flatten
  case _ => Stream.empty
}
// returns Stream[Foo]