Uploaded image for project: 'TinkerPop'
  1. TinkerPop
  2. TINKERPOP-1750

An Object Graph Mapping Framework For Gremlin

    XMLWordPrintableJSON

Details

    • Improvement
    • Status: Closed
    • Major
    • Resolution: Won't Do
    • 3.3.0
    • None
    • structure, tinkergraph
    • None

    Description

      Here, we describe a framework that puts an object-oriented spin on the Gremlin property graph. It aims to make it much easier to specify business DSLs around Gremlin.

      Object Model

      Every element in the property graph, whether it be a vertex (property) or an edge, is made up of properties, each of which is a String key and an arbitrary Java value. It only seems fitting then to try and represent that property as a strongly-typed Java field. The specific class in which that field is defined then becomes the vertex (property) or edge.

      Let's consider the example of the person vertex, taken from the TinkerFactory. In our object world, it would be defined as a Person class that extends a Vertex class like so:

      @Data
      @Alias(label = "person")
      public class Person extends Vertex {
      
        public static ToVertex KnowsPeople = traversal -> traversal
            .out(Label.of(Knows.class))
            .hasLabel(Label.of(Person.class));
      
        @PrimaryKey
        private String name;
      
        @OrderingKey
        private int age;
      
        private Set<String> titles;
      
        private List<Location> locations;
      }
      

      The person's name and age properties become primitive fields in the class. The KnowsPeople field in this class is an example of an in-line SubTraversal, which is just a reusable function that performs certain steps on a GraphTraversal.

      Its titles field, which is defined to be a Set, takes on the set cardinality. Similarly, the locations field gets the list cardinality. Since each location has it's own meta-properties, it deserves a Location class of it's own.

      @Data
      public class Location extends Element {
      
        @OrderingKey
        @PropertyValue
        private String name;
        @OrderingKey
        private Instant startTime;
        private Instant endTime;
      }
      

      The value of the location is stored in name, due to the placement of the @PropertyValue annotation. Every other field in that class becomes the location's meta-property.

      Updating Objects

      The Graph interface lets you update the graph using Vertex or Edge objects. Below, a person vertex containing a list of locations is added, along with three outgoing edges.

      graph
          .addVertex(
              Person.of("marko",
                  Location.of("san diego", 1997, 2001),
                  Location.of("santa cruz", 2001, 2004),
                  Location.of("brussels", 2004, 2005),
                  Location.of("santa fe", 2005))).as("marko")
          .addEdge(Develops.of(2010), "tinkergraph")
          .addEdge(Uses.of(Proficient), "gremlin")
          .addEdge(Uses.of(Expert), "tinkergraph")
      

      Since the object being added may already exist in the graph, we provide various ways to resolve "merge conflicts", such as MERGE, REPLACE, CREATE, IGNORE and INSERT.

      Querying Objects

      Next, let's see how to use the Query interface. The following snippet queries the graph by a chain of SubTraversals, and parses the result into a list of Person vertices.

      List<Person> friends = query
          .by(HasKeys.of(modern.marko), Person.KnowsPeople)
          .list(Person.class);
      

      Below, we query by an AnyTraversal (a function on the GraphTraversalSource), and get a single Person back.

      Person marko = Person.of("marko");
      Person actual = query
          .by(g -> g.V().hasLabel(marko.label()).has("name", marko.name()))
          .one(Person.class);
      
      Service Provider Interface

      To become a gremlin-objects provider, you would need to implement the GraphSystem, which supplies a GraphTraversalSource. And then, extend the ObjectGraph and ObjectQuery abstract classes, constructor injecting your GraphSystem.

      For more details, please see the readme file in the the pull request that I'm about to submit, which also comes with a reference implementation based on TinkerGraph. While I also have a DataStax implementation, which we use at Elementum, a supply chain graph company, it isn't included since it depends on an older TinkerPop version.

      Attachments

        Issue Links

          Activity

            People

              Unassigned Unassigned
              karthick Karthick Sankarachary
              Votes:
              1 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: