[ https://issues.apache.org/jira/browse/TINKERPOP-1750?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Karthick Sankarachary updated TINKERPOP-1750: --------------------------------------------- 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. h5. 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: {code:java} @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; } {code} 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. {code:java} @Data public class Location extends Element { @OrderingKey @PropertyValue private String name; @OrderingKey private Instant startTime; private Instant endTime; } {code} 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. h5. 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. {code:java} 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") {code} 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}}. h5. 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. {code:java} List<Person> friends = query .by(HasKeys.of(modern.marko), Person.KnowsPeople) .list(Person.class); {code} Below, we query by an {{AnyTraversal}} (a function on the {{GraphTraversalSource}}), and get a single {{Person}} back. {code:java} Person marko = Person.of("marko"); Person actual = query .by(g -> g.V().hasLabel(marko.label()).has("name", marko.getName())) .one(Person.class); {code} h5. 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|https://github.com/karthicks/tinkerpop/blob/df6474dda72cd8718af9b7686a52e46d05c20014/gremlin-objects/README.asciidoc] 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. was: 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. h5. 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: {code:java} @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; } {code} 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. {code:java} @Data public class Location extends Element { @OrderingKey @PropertyValue private String name; @OrderingKey private Instant startTime; private Instant endTime; } {code} 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. h5. 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. {code:java} 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") {code} 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}}. h5. 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. {code:java} List<Person> friends = query .by(HasKeys.of(modern.marko), Person.KnowsPeople) .list(Person.class); {code} Below, we query by an {{AnyTraversal}} (a function on the {{GraphTraversalSource}}), and get a single {{Person}} back. {code:java} Person marko = Person.of("marko"); Person actual = query .by(g -> g.V().hasLabel(marko.label()).has("name", marko.getName())) .one(Person.class); {code} h5. 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. > An Object Graph Mapping Framework For Gremlin > --------------------------------------------- > > Key: TINKERPOP-1750 > URL: https://issues.apache.org/jira/browse/TINKERPOP-1750 > Project: TinkerPop > Issue Type: Improvement > Components: structure, tinkergraph > Affects Versions: 3.3.0 > Reporter: Karthick Sankarachary > > 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. > h5. 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: > {code:java} > @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; > } > {code} > 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. > {code:java} > @Data > public class Location extends Element { > @OrderingKey > @PropertyValue > private String name; > @OrderingKey > private Instant startTime; > private Instant endTime; > } > {code} > 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. > h5. 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. > {code:java} > 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") > {code} > 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}}. > h5. 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. > {code:java} > List<Person> friends = query > .by(HasKeys.of(modern.marko), Person.KnowsPeople) > .list(Person.class); > {code} > Below, we query by an {{AnyTraversal}} (a function on the > {{GraphTraversalSource}}), and get a single {{Person}} back. > {code:java} > Person marko = Person.of("marko"); > Person actual = query > .by(g -> g.V().hasLabel(marko.label()).has("name", marko.getName())) > .one(Person.class); > {code} > h5. 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|https://github.com/karthicks/tinkerpop/blob/df6474dda72cd8718af9b7686a52e46d05c20014/gremlin-objects/README.asciidoc] > 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. -- This message was sent by Atlassian JIRA (v6.4.14#64029)