Please note that the latest jazz is happening in the tinkerpop3 branch - it's a complete rewrite and this is where the future is! It's not really ready to use but if you want to have a sneak preview have a look. It already features fully typed traversals, i.e. if you go graph.V.outE.inV.property[String]("someName").path
you get elements of type Vertex :: Edge :: Vertex :: String :: HNil
.
If you would like to help: the readme on the branch lists a couple of things that need attention ;)
A thin wrapper for Gremlin to make it easily usable for Scala Developers. Gremlin is a graph DSL for traversing a number of graph databases including Neo4j, OrientDB, DEX, InfiniteGraph, Titan, Rexster graph server, and Sesame 2.0 compliant RDF stores.
For more information about Gremlin see the Gremlin docs, Gremlin wiki. Gremlin-Steps and Methods. If you have a question please check out 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 ;)
The test specifications are documenting how you can use Gremlin-Scala, this is an excerpt from SampleUsageTest.scala:
describe("Usage with Tinkergraph") {
it("finds all names of vertices") {
vertices.name.toList should be(List("lop", "vadas", "marko", "peter", "ripple", "josh"))
}
it("has different ways to get the properties of a vertex") {
val vertex = graph.v(1)
//dynamic invocation for property is untyped and may return null, like the groovy dsl
vertex.name should be("marko")
vertex.nonExistentProperty should equal(null)
//apply method returns Any type
vertex("age") should be(29)
vertex("nonExistentProperty") should equal(null)
//property returns Some[A] if element present and of type A, otherwise None
vertex.property[Integer]("age") should be(Some(29))
vertex.property[String]("age") should be(None)
vertex.property[Int]("age") should be(None)
vertex.property("nonExistentProperty") should equal(None)
}
it("finds everybody who is over 30 years old") {
vertices.filter {
_.property[Integer]("age") match {
case Some(age) if age > 30 ⇒ true
case _ ⇒ false
}
}.propertyMap.toList should be(List(
Map("name" -> "peter", "age" -> 35),
Map("name" -> "josh", "age" -> 32)))
}
it("finds who marko knows") {
val marko = graph.v(1)
marko.out("knows").map { _("name") }.toList should be(List("vadas", "josh"))
}
it("finds who marko knows if a given edge property `weight` is > 0.8") {
val marko = graph.v(1)
marko.outE("knows").filter { e: Edge ⇒
e.property[java.lang.Float]("weight") match {
case Some(weight) if weight > 0.8 ⇒ true
case _ ⇒ false
}
}.inV.propertyMap.toList should be(List(Map("name" -> "josh", "age" -> 32)))
}
it("finds all vertices") {
vertices.count should be(6)
vertices.propertyMap.toList should be(List(
Map("name" -> "lop", "lang" -> "java"),
Map("age" -> 27, "name" -> "vadas"),
Map("name" -> "marko", "age" -> 29),
Map("name" -> "peter", "age" -> 35),
Map("name" -> "ripple", "lang" -> "java"),
Map("name" -> "josh", "age" -> 32)))
}
describe("Usage with empty Graph") {
it("creates a vertex with properties") {
val graph = new TinkerGraph
val id = 42
val vertex = graph.addV(id)
vertex.setProperty("key", "value")
graph.v(id).key should be("value")
}
it("creates vertices without specific ids") {
val graph = new TinkerGraph
graph.addV()
graph.addV()
graph.V.count should be(2)
}
it("creates edges between vertices") {
val graph = new TinkerGraph
val v1 = graph.addV()
val v2 = graph.addV()
graph.addE(v1, v2, "label")
val foundVertices = v1.out("label").toList
foundVertices.size should be(1)
foundVertices.get(0) should be(v2)
}
}
describe("Graph navigation") {
it("follows outEdge and inVertex") {
graph.v(1).outE("created").inV.name.toList should be(List("lop"))
}
}
}
// sbt: cross released for scala 2.11 and 2.10
"com.michaelpollmeier" %% "gremlin-scala" % "2.6.0"
<!-- Maven -->
<dependency>
<groupId>com.michaelpollmeier</groupId>
<artifactId>gremlin-scala_2.11</artifactId>
<version>2.6.0</version>
</dependency>
You can play with Gremlin in an interactive console in gremlin-standalone/bin/gremlin-scala.sh: Download
\,,,/
(o o)
-----oOOo-(_)-oOOo-----
# create a sample in-memory graph
gremlin> val g = TinkerGraphFactory.createTinkerGraph
==> tinkergraph[vertices:6 edges:6]
# list all vertices
gremlin> g.V
==> v[3]
==> v[2]
==> v[1]
==> v[6]
==> v[5]
==> v[4]
# show properties map of the vertices
gremlin> g.V.propertyMap
==> {name=lop, lang=java}
==> {name=vadas, age=27}
==> {name=marko, age=29}
==> {name=peter, age=35}
==> {name=ripple, lang=java}
==> {name=josh, age=32}
# show names of all vertices
gremlin> g.V.name
==>lop
==>vadas
==>marko
==>peter
==>ripple
==>josh
# get marko's vertex
gremlin> val marko = g.v(1)
==> v[1]
gremlin> marko.age
==> 29
# find marko's friends' names
gremlin> marko.out("knows")(_.name)
==> vadas
==> josh
# create a new graph with two vertices and an edge between them
val g = new TinkerGraph()
val v1 = graph.addV()
val v2 = graph.addV()
graph.addE(v1, v2, "label")
For many more examples (in Gremlin-Groovy syntax) see the [Getting started page of Gremlin (in groovy syntax)]https://github.com/tinkerpop/gremlin/wiki/Getting-Started].
This is a normal Scala REPL, so you run arbitrary Scala code here.
Rexster is a RESTful server for the Tinkerpop stack. It comes with a Console that let's you execute ad hoc Gremlin queries on the configured graphs inside a REPL. In order to use Gremlin-Scala in that Console, just follow these simple steps:
- download the dropin.zip
- unzip the four jars into rexster-standalone/ext
- Add this block to rexster-standalone/config/rexster.xml inside :
<script-engine>
<name>gremlin-scala</name>
</script-engine>
- start the console: bin/rexster-console.sh For more information see the Rexster Console Wiki.
And this is how you switch the language to Gremlin-Scala and execute a simple query:
rexster[groovy]> ?scala
rexster[scala]> val g = rexster.getGraph("tinkergraph")
==>g: com.tinkerpop.blueprints.Graph = tinkergraph[vertices:6 edges:6 directory:data/graph-example-1]
rexster[scala]> g.v(1).name
==>res1: Any = marko
Gremlin-Scala should be as idiomatic Scala as possible, i.e. you can work with Scala's Option type instead of dealing with nulls etc. However, I want to stick close to Gremlin-Groovy, so that it still feels like a real Gremlin and we can use the existing documentation. Often you have multiple ways to achieve the same. Example 1: Gremlin defines a step transform, which in functional Scala land is typically called map. Gremlin-Scala simply defines both, so it's your choice which one to use. I encourage you to use map. Example 2: to access the properties of elements (vertices or edges) you have the following options:
element.someProp //return type: Any, could be null
element[Int]("intProp") //returns an Int, throws ClassCastException for wrong type
element.property[Int]("intProp") //returns Some[Int] if property defined, otherwise None. Idiomatic Scala
Check out the sample usage above for more details.
Shortest path algorithm with Gremlin-Scala 2.4.1 (Stefan Bleibinhaus)
git clone https://github.com/mpollmeier/gremlin-scala.git
sbt test #run all tests (optional)
sbt publish-local #so you can use it in your project
Michael Pollmeier - project maintainer since Gremlin 2.2
Marko Rodriguez and Zach Cox - started this project
Tinkerpop team - created a whole awesome stack around graph databases
Antonio - helped with jsr223 script engine