How does gremlin step .dedup('from' , 'to'') works? - gremlin

Gremlin step .dedup('from' , 'to') remove elements with the same from AND to values or with the same from OR to values?
I need AND so I made that in this way:
.select('from' , 'to').as('hash').dedup('hash')

The strings provided to dedup() refer to as() labels used earlier in the traversal. There is an example here. http://tinkerpop.apache.org/docs/current/reference/#dedup-step
It's not really 'from' , 'to' as much as parts of the path history. As the example shows you can think of it as being an AND where if the same path segment appears more than once dedup('a','b') will remove it.

Related

QGIS - rules. Finding roads crossing cities with query

On same layer in QGIS I have highways (primary, secondary etc.) and cities boundaries (place=city). I want to show/label only primary roads crossing cities. I try something like
"highway" = 'tertiary' AND "place" = 'city'
but got no items, when
"highway" = 'tertiary'
alone returns 6 elements.
Or maybe another way? How can I find crossing elements?
Since both your target variables are in the same layer it seems to be a query problem.
Have you checked if the condition that you are looking for really exists in your dataset?
If so, like many things in QGIS, Rule-based Labeling uses Structured Query Language (SQL), which is strongly typed, to fetch the data you are looking for. Thereby, it's important to be sure about the data types of your dataset and be aware of the double-quote pattern for "column" and single quote for the 'values', if they are varchar or string, exactly as you already did in your example.
Furthermore, check if the values that you are trying to match, in your Rule-based Labeling, are written exactly as they appear in your data attribute table. Anyway, if your dataset is huge, you can use this approach as a workaround:
"highway" ilike '%tertiary% and "place" ilike '%city%'
The ilike operator will make no difference from the upper or lower case in your query, which means that if you have a value 'Tertiary' it would be possible to fetch the data anyway.
Besides, as I put it, the wildcard character % finds any values that have the strings 'tertiary' and 'city' in any position, which can avoid lots of headaches due to whitespaces before or after the string.

gremlin query using select() in coalesce() step

I'm trying to access the previously saved traversal using .as() in the second traversal inside coalesce() as below:
query to upsert edge (update edge if present / create)
Java code:
g.V('x').as('start')
.V('y').as('stop')
.inE('label').where(outV().as('edge'))
.select('start','stop','edge').fold()
.coalesce(unfold(),
addE('label').from(select('start')).to(select('stop')))
.property('key','value')
.promise(Traversal::Next);
Throws error as below: (precised for brevity)
gremlin.driver.exception.ResponseException: The provided traverser does not map to a value [stop]
when i replace the last step as below its working fine (instead of alias querying the vertices again)
Replaced addE('label').from(select('start')).to(select('stop'))
with addE('label').from(V('x')).to(V('y'))
Is there anyway to refer the alias in the second traversal in coalesce?
Note: I'm collecting all data related to finding edges before coalesce in order to make the gremlin throw error when any of the vertex / vertices are missing while creating edge
Expected behaviour: True on successful transaction and error when any vertex missing while creating edge.
This works as expected without using as() alias. But, i'm trying with as(). which i couldn't make it.
Hope this is clear. Please comment if in need of more info. Thanks.
The reason you cannot select the labels 'start' and 'stop' is that you used fold() after defining them. fold() is a reducing barrier step that causes all the labels defined before it to be lost.
Before I explain the solution, here is the traversal to add the two test vertices.
g.addV().property(id, 'x').
addV().property(id, 'y')
The following traversal returns the string 'error' if any of the vertices 'x' or 'y' is missing. If both vertices exist, it upserts the edge (updates the edge if present or adds it if not present).
g.inject(1).
optional(V('x').as('start')).
choose(
select('start'),
optional(V('y').as('stop')).
choose(
select('stop'),
coalesce(
select('start').outE('label').as('e').inV().where(eq('stop')).select('e'),
addE('label').from('start').to('stop')).
property('key', 'value'),
constant('error')),
constant('error'))

Gremlin: removing duplicate values while using as()

This is my graph example:
The picture shows my example for graphdb, the question is: I wanted to get the suggestion friends for jetse ?
Here is the vertices and edges creation for this example
I tried different queries. Sometimes I get column reference error, but I found a solution, but I'm sure its not optimal solution.
Starting Vertices: jetse
all vertices have property called: fname
edges: Works,KNOWS,Teaches,Enroll
what im trying to do is: 1- jetse works in itph, get people who work with jetse which STEF, people who know stef is Remsy, remsy teaches a course where there studendts.
the problem is when i output the result:
stef
remsey
Omar
stef
remsey
ufuk1
becuase they both have the vairables with them.
I want the result like
Stef Remsey Omar ufuk1 ufuk2
My solution is:
g.V('jetse').as('exclude').
out('works').
in().as('sug').
where(neq('exclude')).
in('knows').as('b').
out('teaches').
in('enroll').as('std').
union(select('sug').by('fname'),
select('b').by('fname'),
select('std').by('fname')).
dedup()
Do you have a better query for this solution ?
thanks for tiny-wa for giving me confidence about my answer.
g.V('jetse').as('exclude').
out('works').
in().as('sug').
where(neq('exclude')).
in('knows').as('b').
out('teaches').
in('enroll').as('std').
union(select('sug').by('fname'),
select('b').by('fname'),
select('std').by('fname')).
dedup()

Gremlin - search for multiple substrings

For a given vertex, I can find whether a property myproperty contains a single substring substring1, as so:
g.V(993280096)
.filter({it.get().value("myproperty").contains("substring1")})
How can I extend this to search for multiple substrings in the same query?
Something along the lines of:
g.V(993280096)
.filter({ it.get().value("myproperty")
.contains(or("substring1", "substring2"))})
And is there a better way to do this instead of using lambda expressions? Note that I do not want to use the graph database (in my case JanusGraph) builtins because I'm using gremlin-python.
You can use the new text filter predicates. On the modern sample graph you could do this for example:
gremlin> TinkerFactory.createModern().traversal().V().
has("name", containing("ark").or(containing("os"))).values("name")
==>marko
==>josh
Just after posting I identified a solution (though I don't know if this is the best way) using matches instead of contains:
g.V(993280096)
.filter({ it.get().value("myproperty").matches(".* substring1.*|.* substring2.*")})

How, with Gremlin, to return properties from in-vertices the same as I do from out-vertices? (Not as arrays)

I'm trying to start traversing from one set of labelled vertices, then get all their in-vertices connected by a particular kind of edge, then from there, return a property of those in-vertices as objects. I can do this same thing with some out-vertices starting from the same set of labelled vertices with no problem, but get a "The provided traverser does not map to a value:" error when I attempt it with some in-vertices.
I have found a workaround, but it is not ideal, as it returns the desired property values as arrays of length one.
Here is how I do the very similar task successfully with out-vertices:
g.V().hasLabel('TestCenter').project('address').by(out('physical').project('street').by(values('street1')))
This returns things like
==>{address={street=561 PLACE DE CEDARE}}
==>{address={street=370 N BLACK STATION AVE}}
This is great!
Then I try the same sort of query with some in-vertices, like this:
g.V().hasLabel('TestCenter').project('host').by(__.in('hosts').project('aCode').by(values('code')))
and get the above mentioned error.
The workaround I've been able to find is to add a .fold() to the final "by" like this:
g.V().hasLabel('TestCenter').project('host').by(__.in('hosts').project('aCode').by(values('code')).fold())
but then my responses are like this
==>{host=[{aCode=7387}]}
==>{host=[{aCode=9160}]}
What I would like is a response looking like this:
==>{host={aCode=4325}}
==>{host={aCode=1234}}
(Note: I am not sure if this is relevant, but I am connecting Gremlin to a Neptune DB Instance)
It seems to me from the error above and your workaround that not all of your 'TestCenter' have an in edge from type 'hosts'. When using project the by have to map for a valid value.
you can do two things:
1) make sure a value will be returned in the project:
g.V().hasLabel('TestCenter').project('host')
.by(coalesce(__.in('hosts').project('aCode').by(values('code')), constant('empty')))
2) filter does values:
g.V().hasLabel('TestCenter').where(__.in('hosts'))
.project('host').by(__.in('hosts').project('aCode').by(values('code')))

Resources