Displaying level in gremlin query - graph

I am executing the gremlin query as follows:
g.V().hasLabel('A').has('label_A','A').emit().repeat(outE().inV()).valueMap()
Getting the desired output of nodes at multiple levels.
Along with the properties, I want to add a level property to the output. How can I achieve it?

Adding another answer to point out you can avoid sack using loops as an alternative.
g.V().hasLabel('A').has('label_A','A').
emit().
repeat(group('x').by(loops()).by(valueMap().fold()).out()).
cap('x')

You can use withSack for depth:
g.withSack(0).V().hasLabel('A').has('label_A','A').emit().
repeat(sack(sum).
by(constant(1)).
out()).
project('depth', 'properties').
by(sack()).
by(valueMap())
example: https://gremlify.com/ca32zczgvtkh6

Related

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')))

How to source statments with neoj4 graph database?

I'm looking forward to use NeoJ4 for some researchs. However I have to check if it can do what I want first.
I would like to build a graph that says :
StatementID1 = Cannabidiol hasPositiveEffectOn ChronicPain
StatementID1 isSupportedBy Study1
StatementID1 isSupportedBy Study2
StatementID1 isNotSupportedBy Study3
This is easy to add key:Value properties to a relationship in NeoJ4.
The difficulty is that I want Study1,2,3 to be nodes. So that these can have them own set of properties.
This can be done in a triplestore where each triple has an ID like "Statment1" here. This is a matter of adding triples where the object is another triple ID.
url:TripleID1 = url:Cannabidiol url:hasPositiveEffectOn url:ChronicPain
url:TripleID2 = url:TripleID1 url:isSupportedBy url:Study1
url:TripleID3 = url:TripleID1 url:isSupportedBy url:Study2
url:TripleID4 = url:TripleID1 url:isNotSupportedBy url:Study3
For the moment I can't find how to do it simplely in NeoJ4.
I could add the DOI of the study as a property :
Study 1 :
DOI:123/123
Then add the same DOI in the link :
isSupportedBy:
DOI:123/123
Since the DOI is unique it could be possible to make some searchs. However this will make things much more complex.
Is there a simpler method to achieve that?
I suppose this is a database design issue.
Would a node/relationship model something like the following fit your data and make your queries easy?
Neo4j doesn’t support edges going from an edge to a node. Edges are always between nodes. So you’ll have to convert your positiveEffect edge to a node (as proposed in rickhg12hs’s answer) or model the positiveEffect as a non-edge (as you yourself proposed).

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

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.

Resources