Gremlin is the graph traversal language for the Apache TinkerPop graph framework and is supported by most graph database implementations.
Define a Vertex
@Element("Person")
data class Person(
@ID
val id: Long? = null,
@Property("name")
val name: String)
Define a Relationship
val friends = ManyToManySymmetricEdgeSpec<Person>("friends")
val subordinates = SingleToManyEdgeSpec<Person, Person>("boss_to_subordinates")
val boss = subordinates.inverse
Save a Vertex
val mighael = graphMapper.saveV(Person(name = "Michael Scott"))
val dwight = graphMapper.saveV(Person(name = "Dwight Schrute"))
Save an Edge
graphMapper.saveE(friends from michael to dwight)
graphMapper.saveE(boss from michael to dwight)
Traverse an Edge
graphMapper.traverse(friends from michael) // returns List<Person> [ dwight ]
graphMapper.traverse(friends from dwight) // returns List<Person> [ michael ]
graphMapper.traverse(subordinates from michael) // returns List<Person> [ dwight ]
graphMapper.traverse(boss from dwight) // returns non-optional Person micheal
The graphMapper
is an implementation of the GraphMapper
interface which requires two properties:
- A
GraphTraversalSource
spawned from a tinkerpop graph - A
GraphDescription
which is easily instantiated usingCachedGraphDescription(vertices = setOf(Person::class))
An interactive example can be run using the starwars example project. From the repo root directory, run:
./gradlew run
Then load GraphiQL at http://localhost:5000/graphiql.html
to explore the data mapped with this library.
A small typescript + apollo + react web client that uses this starwars API can also be sampled:
cd example/frontend && yarn start
Then load http://localhost:3000
(server must also be running)
-
Gradle
compile 'com.github.pm-dev:kotlin-gremlin-ogm:0.21.0'
-
Maven
<dependency> <groupId>com.github.pm-dev</groupId> <artifactId>kotlin-gremlin-ogm</artifactId> <version>0.21.0</version> </dependency>
Mix and match the following extensions to this library
- JanusGraph: kotlin-janusgraph-ogm
- GraphQL: kotlin-gremlin-graphql
- ReactiveX: kotlin-rx-ogm
- Take full advantage of Kotlin's type-safety. Traversals return either a list, non-optional, or optional based on whether a relationship is defined as to-many, to-single, or to-optional, respectively.
- Map and filter traversals using your Kotlin objects.
- No runtime code generation. Other ogms use third-party libraries that generate new classes at runtime.
- External dependencies are limited to: Kotlin's standard library, the gremlin-driver, and slf4j.
- Annotation-based so you can bring your current POJO domain objects.
- Kotlin compiler plugins 'all-open' and 'no-arg' are not required.
- Graph databases are powerful for modeling data that is highly connected.
- This OGM enables for strong typing of domain objects in the application layer while removing the need for a schema enforced by the db.
- This allows for data to be backed by a NoSQL datastore. NoSQL datastores are horizontally scalable and can be partition tolerant.
- This makes migrations much easier.
- This library will not work if you're trying to connect to a Gremlin Server remotely. This library creates traversals
that call back into the library, thus, your graph implementation must be running within the same JVM.
- For this reason, connecting to Amazon Neptune is not currently supported, as Amazon Neptune does not support calling arbitrary java from within a traversal.
- Common use-cases should be easy. Uncommon use-cases should be possible.
- Performance is important.
- Fail fast with helpful exceptions.
Boolean
Byte
Double
Float
Int
Long
String
If your Gremlin implementation does not support one of these native types, make sure to register a
property mapper for they type with your GraphDescription
or declare a @Mapper
for that property.
To use other property types, register your custom property mapper with GraphDescription
by returning a PropertyMapper
from the getScalarPropertyMapper
function
a @Mapper
for that property.
- A description of your graph, based annotations, is processed and cached when your
GraphMapper
is instantiated. - Using this description of the graph, we can create 'vertex mappers' that know how to serialize/deserialize objects marked with
@Element
to/from the graph. - Nested objects are not natively supported by Gremlin. When mapping a nested object to properties of a vertex, the property key uses periods ('.') to denote a nested object. For example:
Given:
class Name(val first: String, val last: String)
class Person(val name: Name)
...is serialized in the graph using vertex properties:
"name.first" -> "Lionel"
"name.last" -> "Messi"
List
andSet
types are supported. These collections are stored as follows:
Given:
class Name(val first: String, val last: String)
class Person(val names: Set<Name>)
...is serialized in the graph using vertex properties:
"names.0.first" -> "Cassius"
"names.0.last" -> "Clay"
"names.1.first" -> "Muhammad"
"names.1.last" -> "Ali"
To preserve the difference between a null and empty collection or map, we use
a special UUID
token. For example if the names Set
was empty:
"names" -> "474A56F1-6309-41B5-A632-AD53F57DBDAE"
...or in the case of an empty map, the special UUID
is: 9B94DCB9-D405-47C1-B56D-72F83C4E81D3
.
Licensed under the Apache Software License 2.0. This code is in no way affiliated with, authorized, maintained, sponsored or endorsed by the Apache Software Foundation.