1
votes

I am extending sparql-to-gremlin code to support fully and partially unbound predicate queries that can be used by automated processes to explore the graph structure. The idea being that you could just connect to some graph DB and ask a fully unbound query with some limit and get vertex properties, edge types, edge properties, etc. That can then be explored more.

I can now solve a fully unbound query and can solve one that has the subject bound to a vertex. Now I am trying to put it together into a multi-literal query and finding that the Gremlin MATCH Step would need to reflect on the type of Traversal before it can decide which steps would actually apply. For example if, the Traversal results in a Vertex, asking for out/in edges and properties makes sense; if it’s an Edge though, asking for out/in edges does not make sense and actually results in errors about unexpected type being thrown.

Thus the question, is it possible to write a kind of “switch” statement that would reflect on the type and then only ask for things that makes sense in that context?

Here’s one type of SPARQL query that I am trying to support (based on the Graph of the Gods described here https://old-docs.janusgraph.org/0.1.0/getting-started.html):

https://old-docs.janusgraph.org/0.1.0/images/graph-of-the-gods-2.png

SELECT ?BATTLE ?PRED ?VALUE
WHERE {
    vid:6 ep:battled ?BATTLE .
    ?BATTLE ?PRED ?VALUE .
}

Here we are starting from a vertex with id 6, grabbing the outgoing edge reference with “battled” label, then grabbing all possible properties of the edge along with their values.

Here vertex with id 6 is Hercules, which has 3 outgoing edges with label “battled” going to vertex with id 9 (Nemean), 10 (Hydra) and 11 (Cerberus). I would want to the have ?PRED be bound to v:id (edge id), v:label (edge label), v:time (edge time property value), v:place (edge place property value), eps:battled (an extension to sparql-to-gremlin relating edge to an IN vertex).

1
wouldn't it make more sense to work together with the gremlinator guys then? I mean Harsh Thakkar and the other people behind this topic? This is basically a research topic and there are still feature not supported. I can tell you, you can't do anything via SPARQL and especially not via a single SPARQL query.UninformedUser
Honestly, I also didn't quite catch what the question now is? Is this a SPARQL specific question? The only kind of "switch" in SPARQL is IF, but even this is limited. Maybe you can explain what you need in your current SPARQL query? I'm clearly missing something obvious, so far itz just get's all outgoing (p, o) bindings for each binding of a battle. Restricting to just a few properties based on some type could be done via a separate graph pattern, but I guess this is not what you need?UninformedUser
I am not trying to come up with a different SPARQL query, the one I mentioned in the question is a valid SPARQL query and should be translatable to Gremlin via Gramlinator with a bit more work. The problem I am having right now is that I need to know what kind of type ?BATTLE is so that I ask for "predicates" that make sense. In this particular instance ?BATTLE will be Edge, but I can replace the first literal with vid:6 e:battle ?BATTLE, in which case we'd get the other vertex that connects to vid:6 through "battle" edge - ?BATTLE type would be a Vertex.anton

1 Answers

0
votes

I think that I follow your problem and I don't think I have a good answer for you. At the moment, Gremlin isn't terribly good with type detection and the issue remains open on TINKERPOP-2234. The typical workaround for most people when they have a mixed set of elements in a stream is to use a step like coalesce() or choose() to act as a form of switch statement and then figure out some filter than can identify the object type. So here's some mixed results that I've contrived:

gremlin> g.V().union(outE(),__.in())
==>e[9][1-created->3]
==>e[7][1-knows->2]
==>e[8][1-knows->4]
==>v[1]
==>v[1]
==>v[4]
==>v[6]
==>e[10][4-created->5]
==>e[11][4-created->3]
==>v[1]
==>v[4]
==>e[12][6-created->3]

and then I test with hasLabel() for labels I know to belong to vertices only, then everything else must be an edge:

gremlin> g.V().union(outE(),__.in()).choose(hasLabel('person','software'), values('name'), values('weight'))
==>0.4
==>0.5
==>1.0
==>marko
==>marko
==>josh
==>peter
==>1.0
==>0.4
==>marko
==>josh
==>0.2

Not ideal obviously but it typically resolves most people's problems. Hopefully we will see TINKERPOP-2234 solved for 3.5.0.

Another possible workaround is to use a lambda which works well for some use cases though we try to avoid them when possible:

gremlin> g.V().union(outE(),__.in()).choose(filter{it.get() instanceof Vertex}, values('name'), values('weight'))
==>0.4
==>0.5
==>1.0
==>marko
==>marko
==>josh
==>peter
==>1.0
==>0.4
==>marko
==>josh
==>0.2