Data: Tinkerpop Modern sample graph
Query:
gremlin> g.V(1).repeat(both()).until(hasLabel("person")).path().by("name")
==>[marko,vadas]
==>[marko,josh]
==>[marko,lop,marko]
==>[marko,lop,josh]
==>[marko,lop,peter]
What doc says:
...If until() comes after repeat() it is do/while looping. If until()
comes before repeat() it is while/do looping...
Doubt:
Shouldn't until terminate the query after first match marko-vadas? or am I missing something?
It terminates the traverser on this path, otherwise you would get [marko,vadas,marko] next. The other paths were found by other traversers. If you only care about the first path, add a .limit(1).
gremlin> g.V(1).repeat(both()).until(hasLabel("person")).limit(1).path().by("name")
==>[marko,vadas]
Related
Is there a way to check how many records were found, and in case less than X records were returned do another query?
For example first run this query ->
g.V().
hasLabel('courseContent').
has('status', 'active').as('cc').
outE('ccBelongsToCourse').
has('status', 'active').
inV().
hasLabel('course').
has('externalId', ':courseId').
select('cc').by(valueMap('externalId')).
dedup().
range(:offSet, :limit);
And in case less than 10 records were found, run this query:
g.V().
hasLabel('educatorContent').
has('status', 'active').as('ec').
select('ec').by(valueMap('externalId')).
dedup().
range(:offSet, :limit);
but do it all inside the same .gremlin file?
(Sorry if the question is too basic, super new to Gremlin)
You could use choose() which provides if-then semantics:
range(:offSet, :limit).fold().
choose(count(local).is(gt(9)),
identity(),
V().has('educatorContent', 'status','active')....)
I am new to gremlin.
I am facing issue in fetching the vertex and edges when sometimes edge from a vertex does not exists.
for example bellow query works fine if it gets all the vertex and edges.
but for one use case edge
`.outE("PRODUCES").`as`("produces"))`
does not exists in db.
in that case bellow query doesnt return any result.
I need your help to resolve this issue.
when edges does not exit then i want input_entity and processed_by in result.
janusGraph.traversal().V()
.has("isActive", "true")
.hasLabel("ENTITY").`as`("input_entity")
.outE("PROCESSED_BY").`as`("processed_by")
.inV().`as`("job")
.outE("PRODUCES").`as`("produces")
.select<String>("job").outE("HAS_STATE")
.`as`("job_state_edge").inV().hasLabel("JOB_STATE").`as`("job_state")
.select<String>("input_entity").outE("HAS_STATE")
.`as`("input_entity_state_edge").inV().hasLabel("ENTITY_STATE").`as`("input_entity_state")
.select<String>("input_entity").outE("CONNECTS_TO").`as`("connects_to")
.inV().hasLabel("ENTITY").has("entityName", TextP.startingWith(rootNamespace))
.`as`("output_entity").outE("HAS_STATE")
.`as`("output_entity_state_edge").inV().hasLabel("ENTITY_STATE").`as`("output_entity_state")
.select<String>("input_entity","output_entity","processed_by","produces","job","job_state","input_entity_state","output_entity_state","input_entity_state_edge","output_entity_state_edge","job_state_edge","connects_to")
.by(elementMap<Element, Any>()).toList()
with optional
janusGraph.traversal().V()
.has("isActive", "true")
.hasLabel("ENTITY").`as`("input_entity")
.outE("HAS_STATE").`as`("input_entity_state_edge").inV().hasLabel("ENTITY_STATE").`as`("input_entity_state")
.select<String>("input_entity").outE("PROCESSED_BY").`as`("processed_by")
.inV().`as`("job").outE("HAS_STATE").`as`("job_state_edge").inV().hasLabel("JOB_STATE").`as`("job_state")
.select<String>("job")
.optional(
outE("PRODUCES").`as`("produces")
.select<String>("input_entity").outE("CONNECTS_TO").`as`("connects_to")
.inV().hasLabel("ENTITY").has("entityName", TextP.startingWith(rootNamespace))
.`as`("output_entity").outE("HAS_STATE").`as`("output_entity_state_edge").inV().hasLabel("ENTITY_STATE").`as`("output_entity_state"))
.select<String>("input_entity","output_entity","processed_by","produces","job","job_state","input_entity_state","output_entity_state","input_entity_state_edge","output_entity_state_edge","job_state_edge","connects_to")
.by(elementMap<Element, Any>()).toList()
There are two Gremlin steps that can help in cases like this. When you have a part of a query that may or may not exist, but you either want the results up to that point if it does not exist or the results afterwards if it does exist, you can wrap that part of the query in an optional step.
For example :
g.V('3').optional(out())
Will either return V['3'] or the adjacent vertices if out yields results.
In cases where you want to select a value that may not exist, you can do something like this:
coalesce(select('a'),constant('No results'))
EDITED to add:
If you need to return multiple results, rather than just using select try a project('a','b,',c') type of approach where each by modulator for the project can contain its own coalesce step.
I am trying to write a gremlin query to get all the edges between a list of vertices.
Data redacted to protect privacy. User A(42651832) -reports_to-> User
B(28729440) -reports_to-> User C(19546208)
ids = [19546208, 28729440, 42651832]
I need to find all the edges between an arbitrary list of vertices
Seems simple, but I am unable to write a query that gives results I need.
gremlin> g.V(42651832).outE('reports_to').otherV().id()
==>28729440
gremlin> g.V(28729440).outE('reports_to').otherV().id()
==>19546208
gremlin> ids = [19546208, 28729440, 42651832]
==>19546208
==>28729440
==>42651832
gremlin> g.V(ids)
==>v[19546208]
==>v[28729440]
==>v[42651832]
gremlin> g.V(ids).bothE().where(otherV().hasId(ids))
gremlin> g.V(ids).bothE().where(otherV().hasId(within(ids)))
gremlin> g.V(ids).bothE().where(otherV().hasId(within(19546208, 28729440, 42651832)))
Apparently, I think there is a type conversion issue between gremlin console and JanusGraph.
quoting as string or converting to Long seems to work.
gremlin> g.V(ids).bothE().where(otherV().hasId(within("19546208", "28729440", "42651832")))
==>e[10r7d8-h3rs0-i6t-bmxy8][28729440-reports_to->19546208]
==>e[10r7d8-h3rs0-i6t-bmxy8][28729440-reports_to->19546208]
==>e[128qvr-pe6d4-i6t-h3rs0][42651832-reports_to->28729440]
==>e[128qvr-pe6d4-i6t-h3rs0][42651832-reports_to->28729440]
gremlin> g.V(ids).bothE().where(otherV().hasId(within(19546208L, 28729440L, 42651832L)))
==>e[10r7d8-h3rs0-i6t-bmxy8][28729440-reports_to->19546208]
==>e[10r7d8-h3rs0-i6t-bmxy8][28729440-reports_to->19546208]
==>e[128qvr-pe6d4-i6t-h3rs0][42651832-reports_to->28729440]
==>e[128qvr-pe6d4-i6t-h3rs0][42651832-reports_to->28729440]
gremlin>
gremlin> g.V(ids).bothE().where(otherV().hasId(within(19546208L, 28729440L, 42651832L))).dedup()
==>e[10r7d8-h3rs0-i6t-bmxy8][28729440-reports_to->19546208]
==>e[128qvr-pe6d4-i6t-h3rs0][42651832-reports_to->28729440]
Any other suggestions. Not sure why JanusGraph works this way.
This isn't quite a full answer, but hopefully it gets you close enough. I used GraphOfTheGods to test it out.
This will get all the paths from the ids list to the quoted ids in hasID() and then output a list of all the edges traversed in each path. I added a limit for readability. You could easily add all the values to a set to get a deduped answer.
# Save all the graph of the gods vertex ids to a variable
ids = [4112,4128,4136,8232,12328,16424,20520,4296,4328,4344,8440,12536]
paths = g.V(ids).until(hasId("8440","12536")).repeat(bothE().aggregate("e").otherV().simplePath()).limit(3).select('e')
==>[e[74v-6ig-9hx-368][8440-battled->4112]]
==>[e[74v-6ig-9hx-368][8440-battled->4112],e[7xb-6ig-9hx-36o][8440-battled->4128],e[1l0-36o-b2t-9o8][4128-lives->12536],e[9vp-co8-bv9-36o][16424-pet->4128]]
==>[e[74v-6ig-9hx-368][8440-battled->4112],e[7xb-6ig-9hx-36o][8440-battled->4128],e[1l0-36o-b2t-9o8][4128-lives->12536],e[9vp-co8-bv9-36o][16424-pet->4128]]
What I was able to originally get was a full path with connecting vertexes which I am including in case it could potentially be helpful.
paths = g.V(ids).until(hasId("8440","12536")).repeat(bothE().otherV().simplePath()).path().limit(5)
==>[v[4112],e[74v-6ig-9hx-368][8440-battled->4112],v[8440]]
==>[v[4128],e[7xb-6ig-9hx-36o][8440-battled->4128],v[8440]]
==>[v[4128],e[1l0-36o-b2t-9o8][4128-lives->12536],v[12536]]
==>[v[4128],e[9vp-co8-bv9-36o][16424-pet->4128],v[16424],e[9hh-co8-b2t-9o8][16424-lives->12536],v[12536]]
==>[v[4128],e[9vp-co8-bv9-36o][16424-pet->4128],v[16424],e[8p1-co8-cnp-3co][16424-brother->4344],v[4344],e[6cf-6ig-7x1-3co][8440-father->4344],v[8440]]
Separately I did some checking with the GraphOfTheGods and the explain() step and it definitely seems like a bug. If I set a list to variable it is performing an equal step instead of a within step.
paths = g.V(ids).until(hasId(ids)).repeat(out().simplePath()).limit(10).path().explain()
...RepeatStep(until([HasStep([~id.eq([4112, 4128, ...])])]),
where as listing in quotes it will properly do a within check.
paths = g.V(ids).until(hasId("8440","12536")).repeat(outE().simplePath()).limit(10).path().explain()
...RepeatStep(until([HasStep([~id.within([8440, 12536])])])
Just getting started with gremlin.
Printing out all the Vertex values worked out fine
gremlin> g.V().values()
==>testing 2
==>Cash Processing
==>Sales
==>Marketing
==>Accounting
I was able to find all the directly connected path between my Vertices.
gremlin> g.V().hasLabel('Process')
.repeat(both().simplePath())
.until(hasLabel('Process'))
.dedup().path()
==>[v[25],v[28]]
==>[v[25],v[26]]
==>[v[26],v[27]]
==>[v[26],v[25]]
Now am trying to print out the values in the path like ['Sales', 'Accounting'] instead of [v[25],v[28]]
Not been able to figure out a way yet
Already tried and failed with
Unfold: Does not get me 1-1 mapping
gremlin> g.V().hasLabel('Process').repeat(both().simplePath()).until(hasLabel('Process')).dedup().path().unfold().values()
==>Cash Processing
==>Accounting
==>Cash Processing
==>Sales
==>Sales
==>Marketing
==>Sales
==>Cash Processing
Path seems to be of a different data-type and does not support .values() function
gremlin> g.V().hasLabel('Process')
.repeat(both().simplePath())
.until(hasLabel('Process'))
.dedup().path().values()
org.apache.tinkerpop.gremlin.process.traversal.step.util.ImmutablePath cannot be cast to org.apache.tinkerpop.gremlin.structure.Element
Tried the following google searches and didnt get the answer
gremlin print a path
gremlin get values in a path
and few more word twisting
Found one at here that was for java but that didnt work for me
l = []; g.V().....path().fill(l)
(but cant create list, Cannot set readonly property: list for class: org.apache.tinkerpop.gremlin.structure.VertexProperty$Cardinality
)
I have running it on Gremlin console (running ./gremlin.sh)
You can use the by step to modulate the elements inside the path. For example by supplying valueMap(true) to by you get the properties of the vertices, together with the vertex labels and their ids:
gremlin> g.V().repeat(both().simplePath()).times(1).dedup().path().by(valueMap(true))
==>[[id:1,name:[marko],label:person,age:[29]],[id:3,name:[lop],lang:[java],label:software]]
==>[[id:1,name:[marko],label:person,age:[29]],[id:2,name:[vadas],label:person,age:[27]]]
==>[[id:1,name:[marko],label:person,age:[29]],[id:4,name:[josh],label:person,age:[32]]]
==>[[id:2,name:[vadas],label:person,age:[27]],[id:1,name:[marko],label:person,age:[29]]]
==>[[id:3,name:[lop],lang:[java],label:software],[id:6,name:[peter],label:person,age:[35]]]
==>[[id:4,name:[josh],label:person,age:[32]],[id:5,name:[ripple],lang:[java],label:software]]
I used the modern graph which is one of TinkerPop's toy graphs that are often used for such examples. Your output will look a bit different and you may want to use something else than valueMap(true) for the by modulator. The TinkerPop documentation of the path step itself contains two more advanced examples for path().by() that you might want to check out.
The following query of the Titan example graph does not produce what I expected:
g.V.has("age", T.lte,1000).as('young').out('battled').has("name","cerberus").copySplit(
_().back('young'),
_()
).exhaustMerge
it gives me twice the cerberus vertex, instead of hercules and cerberus
It appears that back is not working after a copySplit. Is there a way around this limitation?
Already answered on the Gremlin users mailing list, but here we go again:
These 2 alternatives would still work in Gremlin3 (with a slightly different syntax, but the concept is the same):
gremlin> g.V().has("age", T.lte, 1000).as("young").out("battled").has("name", "cerberus").as("monster").select()
==>[young:v[24], monster:v[44]]
Or:
gremlin> g.V().has("age", T.lte, 1000).out("battled").has("name", "cerberus").path()
==>[v[24], v[44]]