Skip to content

joan38/gremlin-scala

 
 

Repository files navigation

logo Build Status Join the chat at https://gitter.im/mpollmeier/gremlin-scala

Gremlin-Scala for Apache Tinkerpop 3

A slim wrapper to make Gremlin - a JVM graph traversal library - usable from Scala. This is the current development branch for Apache Tinkerpop3. The old version for Tinkerpop 2 is still in the 2.x branch.

Benefits

  • Scala friendly function signatures, aiming to be close to the standard collection library
  • Nicer DSL e.g. to create vertices and edges
  • You can use standard Scala functions instead of having to worry about how to implement things like java.util.function.BiPredicate
  • Nothing is hidden away, you can always easily access the Gremlin-Java objects if needed. Examples include accessing graph db specifics things like indexes, or using a step that hasn't been implemented in Gremlin-Scala yet
  • Minimal overhead - only allocates additional instances if absolutely necessary

Getting started

The examples project comes with working examples for different graph databases.

Using the sbt console

  • tl;dr: sbt gremlin-scala/console
  • start sbt in the root project
> projects
[info]     gremlin-scala
[info]     macros
[info]   * root
>
  • Next, change to the gremlin-scala project using project gremlin-scala
  • Finally, to test out the API in a REPL type console

Creating vertices and edges

import gremlin.scala._
import gremlin.scala.schema.Key
import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph
val graph = TinkerGraph.open.asScala

// create labelled vertex
val paris = graph + "Paris"

// create vertex with typed properties
object Founded extends Key[String]("founded")
val london = graph + ("London", Founded("43 AD"))

// create labelled edges 
paris --- "OneWayRoad" --> london
paris <-- "OtherWayAround" --- london

// create labelled bidirectional edge
paris <-- "Eurostar" --> london

// create edge with typed properties
object Name extends Key[String]("name")
paris <-- ("EuroStar", Name("TrainName")) --- london

Many thanks to @dkrieg for contributing this. For more details check out the SchemaSpec.

Compiler helps to eliminate invalid traversals

Gremlin-Scala aims to helps you at compile time as much as possible. Take this simple example:

import gremlin.scala._
import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph
val graph = TinkerGraph.open.asScala
graph.V.outE.inV  //compiles
graph.V.outE.outE //does _not_ compile

In standard Gremlin there's nothing stopping you to create the first traversal - it will explode at runtime, as outgoing edges do not have outgoing edges. This is simply an invalid step and we can use the compiler to help us.

Type safe traversals

Gremlin-Scala has support for full type safety in a traversal. You can label any step you want and in the end call labelledPath - you will the values in each labelled step as an HList. That's a type safe list, i.e. the compiler guarantees the types, which also helps you auto-complete in your IDE. In contrast: in Java and Groovy you would have to cast to the type you think it will be, which is ugly and error prone. For example:

import gremlin.scala._
import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory
val graph = TinkerFactory.createModern.asScala
val traversal = graph.V.as("a").out.value[String]("name").as("b").labelledPath
traversal.toList
// returns `Vertex :: String :: HNil` for each path

You can label as many steps as you like and Gremlin-Scala will preserve the types for you. For more examples see LabelledPathSpec. In comparison: Gremlin-Java and Gremlin-Groovy just return a List[Any] and you then have to cast the elements - the types got lost on the way. Kudos to shapeless and Scala's sophisticated type system that made this possible.

Saving / loading case classes

You can save and load case classes as a vertex - this is still experimental but pretty cool. Note: this does not work in a REPL, you have to put it into a test. For examples check out the MarshallerSpec.

import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph
val graph = TinkerGraph.open.asScala
case class Example(i: Int, s:Option[String])

it("load a vertex into a case class") {
  val graph = TinkerGraph.open.asScala
  val example = Example(Int.MaxValue, Some("optional value"))
  val v = graph.addVertex(example)
  v.toCC[Example] shouldBe example
}

Note that you can also use Options as the example shows. Thanks to joan38 for contributing this feature!

Help - it's open source!

If you would like to help, here's a list of things that needs to be addressed:

Further reading

For more information about Gremlin see the Gremlin docs and the Gremlin users mailinglist. Please note that while Gremlin-Scala is very close to the original Gremlin, there a slight differences to Gremlin-Groovy - don't be afraid, they hopefully all make sense to a Scala developer ;)

Random links:

About

Scala wrapper for Apache TinkerPop 3 Graph DSL

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Scala 98.2%
  • Batchfile 1.1%
  • Shell 0.7%