I am not able to comprehend how to do I effectively use optional() within a match() step.
I am working on transpiling/compiling sparql queries to Gremlin traversals (pattern matching style), mostly everything except the optional() clause checks out just fine. However, I am not able to map the optional() operator.
For reference-
In SPARQL, an optional clause executes an inner-join in the query whereas this is different in the case of Gremlin. e.g.:
SPARQL:
select ?name ?age
where {
?person v:name ?name .
OPTIONAL { ?person v:age ?age .}
}
Here, all person names will be returned regardless of whether or not they have age affiliate to them or not. The age values are optional in this sense. The equivalent query in gremlin should be somewhat like the following, if we were to consider optional() step in Gremlin:
g.V().match(__.as('person').values('name').as('name').optional( __.as('person').values('age').as('age'))).select('name','age')
However, this doesn't work. instead, it throws an error. I am using Gremlin-console v3.3.3
Consider the following gremlin query:
gremlin> g.V().as('a').hasLabel('person').as('person').optional( __.as('a').values('age').as('age')).select('person','age')
==>[person:v[1],age:29]
==>[person:v[2],age:27]
==>[person:v[4],age:32]
==>[person:v[6],age:35]
This works perfectly fine and returns a result. However, if I am to conduct a pattern matching style of a gremlin query, I add a match step in the query encapsulating it within:
gremlin> g.V()..match( __.as('a').hasLabel('person').as('person').optional( __.as('a').values('age').as('age'))).select('person','age')
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal cannot be cast to java.lang.Comparable
Type ':help' or ':h' for help.
However, this throws an error as above. I tried all possible combinations here but always results in one or the other error:
g.V().match(__.as('person').values('name').as('name'), __as('person').optional(values('age').as('age'))).select('name','age')
No signature of method: groovysh_evaluate.__as() is applicable for argument types: (java.lang.String) values: [person]
Possible solutions: is(java.lang.Object), wait(), run(), run(), find(), any()
What i understood so far is that it is not possible to store values directly in the variables while using the optional() step, i.e.:
g.V().as('a').values('name').as('name').optional(__.as('a').values('age').as('age'))).select('name','age')
will not work, because of:
java.lang.String cannot be cast to org.apache.tinkerpop.gremlin.structure.Element
whereas:
gremlin> g.V().as('a').has('name').as('name').optional(__.as('a').values('age').as('age')).select('name','age')
==>[name:v[1],age:29]
==>[name:v[2],age:27]
==>[name:v[4],age:32]
==>[name:v[6],age:35]
Does work fine. I am thinking to not use optional() clause here instead map it to some other operator() such as and() or a workaround to achieve a SQL-like inner join execution. Though no success yet.
If someone could help me fix this, it would be great!
Cheers,
Harsh