Is possible in gremlin to count something inside a choose and then go back to a previous step? - gremlin

Is possible in gremlin to count something inside choose() and then go back to a previous step in the traversal?:
g.V()
.hasLabel("user1")
.as("firstStep")
.V()
.as("secondStep")
.fold()
.choose(
count(local).is(gt(1)),
select('firstStep'),
select('secondStep')
)
The select('firstStep') line is executed but nothing is returned because at that point everything stored by .as("firstStep") was removed by fold()
Of course I can always solve this kind of problem at the expense of performance, duplicating the cost by searching 2 times:
g.V()
.hasLabel("user1")
.choose(
V().fold().count(local).is(lt(2)),
V().fold()
)
I'm looking for a better solution than this.
This is like if I go to a store and pay something, because I have to count the change I forget how to go back to my hose, the gremlins of the movie are more intelligent than that. I hope there is a solution that I ignore.
EDIT:
There is an answer recommending to replace as() by store() but that is not a general solution, doesn't work in most situations becase these are very different tools, for example this query has the same problem and replacing as() by store() gives a different result:
g.V()
.hasLabel('user')
.project("user")
.by(
as("singleUser")
.V()
.fold()
.choose(
count(local).is(gt(1)),
select('singleUser'),
unfold()
)
)

In this pattern you can use store step, that way the "firstStep" will be saved after the fold.
g.V().hasLabel('user1').store('firstStep').
V().
fold().choose(
count(local).is(gt(1)),
select('firstStep').unfold(),
select('secondStep')
)
example: https://gremlify.com/mg7noyf1cdq

Related

Need a query to retrieve complete graph

I am trying to retrieve all the node and properties details in parent-child hierarchy.
Nested within each other.
Since I am new with gremlin, graphDB I am having really tough time to get it done.
Please suggest a solution and if you could walk me through it, it will be great.
Following is my structure
And I am trying to keep the response as clean as possible.
I am using cosmosDB and Gremlin.
NET api for this.
I tried the following but it gave me response in key value,
g.V("some_id").repeat(out()).emit().tree().path()
g.V("some_id").emit().repeat(both().simplePath()).dedup()
please any kind of suggestion would be great.
I"m not sure what format you want your result, but use of path(), tree() or subgraph() would typically give you the graph structure. Since you are using CosmosDB, you're only options are path() and tree() as subgraph() does not appear to be supported.
Using this sample graph as a simple tree:
g.addV().property(id, '1').as('1').
addV().property(id, '2a').as('2a').
addV().property(id, '2b').as('2b').
addV().property(id, '3a').as('3a').
addV().property(id, '4a').as('4a').
addE('child').from('1').to('2a').
addE('child').from('1').to('2b').
addE('child').from('2a').to('3a').
addE('child').from('3a').to('4a')
you can see the effect of path() which basically gathers the contents of each step Gremlin took:
gremlin> g.V('1').repeat(out()).emit().path()
==>[v[1],v[2a]]
==>[v[1],v[2b]]
==>[v[1],v[2a],v[3a]]
==>[v[1],v[2a],v[3a],v[4a]]
Since I used out() we don't see the edges, but that is easily remedied by adding making a small adjustment to directly consume edges into the path history:
gremlin> g.V('1').repeat(outE().inV()).emit().path()
==>[v[1],e[0][1-child->2a],v[2a]]
==>[v[1],e[1][1-child->2b],v[2b]]
==>[v[1],e[0][1-child->2a],v[2a],e[2][2a-child->3a],v[3a]]
==>[v[1],e[0][1-child->2a],v[2a],e[2][2a-child->3a],v[3a],e[3][3a-child->4a],v[4a]]
Taken together with duplication removed on your application side you have a complete graph with path().
Replacing path() with tree() will essentially do that deduplication by maintaining the tree structure of the path history:
gremlin> g.V('1').repeat(out()).emit().tree()
==>[v[1]:[v[2b]:[],v[2a]:[v[3a]:[v[4a]:[]]]]]
gremlin> g.V('1').repeat(outE().inV()).emit().tree()
==>[v[1]:[e[0][1-child->2a]:[v[2a]:[e[2][2a-child->3a]:[v[3a]:[e[3][3a-child->4a]:[v[4a]:[]]]]]],e[1][1-child->2b]:[v[2b]:[]]]]
The Tree is just represented as a Map where each key represents a like a root and value is another Tree (i.e. the branches from it). It is perhaps better visualized this way:
gremlin> g.V('1').repeat(out()).emit().tree().unfold()
==>v[1]={v[2b]={}, v[2a]={v[3a]={v[4a]={}}}}
gremlin> g.V('1').repeat(out()).emit().tree().unfold().next().value
==>v[2b]={}
==>v[2a]={v[3a]={v[4a]={}}}
If neither of these structures are suitable and subgraph() is not available you can technically just capture and return the edges you traverse as the low level elements of your subgraph as described in this blog post.
Given the comments on this answer I also present the following option which used group():
gremlin> g.V('1').emit().
......1> repeat(outE().group('a').by(outV()).by(inV().fold()).inV()).cap('a').unfold()
==>v[1]=[v[2a], v[2b]]
==>v[3a]=[v[4a]]
==>v[2a]=[v[3a]]
It's not exactly a "tree" but if you know the root (in this case v[1]) you can find its key in the Map. The values are the children. You can then look up each of those keys in the Map to find if they have children and so on. For example, we can lookup v[2b] and find that it has no children while looking up [v2a] reveals a single child of [v3a]. Gremlin can be pretty flexible in getting answers if you can be sorta flexible in how you deal with the results.

Select multiple edges and vertexes in a gremlin query

I am creating a vertex with multiple edges but need a bit of help writing a query to retrieve the data.
Creation query
g.addV("referral")
.as("r")
.property("createdAt", Date.now())
.addE("prospect")
.from_("r")
.to(__.V(user.id))
.addE("opportunity")
.from_("r")
.to(__.V(second_user.id))
.addE("referredBy")
.from_("r")
.to(__.V(business.id))
.select("r")
.next()
I want to run a query that gets data from the first and second user. So far I have
g.V(business.id) //business
.in_("opportunity")
.as("referral")
.outV("referredBy")
.as("referrer")
.inV("prospect")
.as("prospect")
.select("referral", "referrer", "prospect")
.toList()
.next()
I'm getting an error when running this query. I basically want an array of a referral, referrer and prospect in one object that I can iterate through. Also any help on making my initial query better would be helpful.
Please let me know if this makes sense or if you need any other info. Any help would be appreciated.
The errors are because you are using outV when you should be using out. You only need to use inV and outV after outE and inE. So your query should be
g.V(business.id) //business
.in("opportunity")
.as("referral")
.out("referredBy")
.as("referrer")
.in("prospect")
.as("prospect")
.select("referral", "referrer", "prospect")
.toList()
Also you don't need next as you already have toList.
Lastly rather than use as and select I would look at the path step instead.
g.V(business.id) //business
.in("opportunity")
.out("referredBy")
.in("prospect")
.path()
.toList()

Gremlin/Neptune: sort edges by vertex property

Using the gremlin console connected remotely to a Neptune DB instance, I am grabbing all edges with a specific label and want to sort them by the id of the out vertex. I'm getting this error: "code":"UnsupportedOperationException","detailedMessage":"com.amazon.neptune.storage.volcano.ast.CutoffNode cannot be cast to com.amazon.neptune.storage.volcano.ast.AbstractGroupNode".
Sample data:
g.addV('user').property(id,'1').
addV('content').property(id,'2').
addE('history').property('val',9).from(g.V('1')).to(g.V('2'))
Queries and outputs:
g.E().hasLabel('history').order().by('val')
==>e[3][1-history>2]
g.E().hasLabel('history').outV().id()
==>1
g.E().hasLabel('history').order().by(outV().id())
{"requestId":<stuff>,"code":"UnsupportedOperationException","detailedMessage":
"com.amazon.neptune.storage.volcano.ast.CutoffNode cannot be cast to
com.amazon.neptune.storage.volcano.ast.AbstractGroupNode"}
I expect the result of that last one to be the same as the first. I've tried the same traversal in a TinkerGraph and didn't get an error, so judging by that and the message it's specifically a Neptune problem. Googling hasn't brought up anything.
Is there a traversal that will do what I'm looking for? What am I doing wrong?
I will look into why the error is being thrown but in the near term I think this workaround should work. Please let me know if it does not.
g.E().order().by(identity().outV().id())
Cheers,
Kelvin

Have Gremlin-console show all the methods available for a specific object?

In gremlin-console, is there a way to show all the methods available for a specific object?
For example, In gremlin-console if I type g.V().hasLabel("person") and I want to see what methods I can chain/call for the object returned by g.V().hasLabel("person"). How do you do that?
The answer is to use the <Tab> key.
gremlin> "test".c
capitalize() center( charAt( chars() codePointAt( codePointBefore( codePointCount( codePoints() collectReplacements( compareTo(
compareToIgnoreCase( concat( contains( contentEquals( count(
However, I'm finding that it is not working for something like g.V().o which I'd hoped would have shown out(). Apparently, the groovy shell (which is what the Gremlin Console is based on) doesn't seem to want to do the auto-complete on a fluent API. It seems to only work on the first object on which you are calling the method:
gremlin> g.
E( V( addV( addV() close() inject( tx() withBindings( withBulk(
withComputer( withComputer() withPath() withRemote( withSack( withSideEffect( withStrategies( withoutStrategies( anonymousTraversalClass
bytecode graph strategies
gremlin> x = g.V();[]
gremlin> x.o
option( optional( or( order( order() otherV() out( outE( outV()
gremlin> x.o
That stinks...that's not really a TinkerPop issue - we rely on the groovysh for that functionality. Not much we can do there I don't think....
Of course, you are using DSE Graph which means you have access to DataStax Studio which not only has the auto-complete that you're looking for but also schema support (and more!). I'd suggest that you switch to that.

Overpass does not find all cinemas - Overpass API documentation

In the openstreetmap overpass API-documentation there is the following example:
area[name="Bonn"];
node(area)[highway=bus_stop];
node(around:100)[amenity=cinema];
out;
Why does this query does not give the Kinopolis (in Bonn Bad Godesberg) as a result? See here: http://rpubs.com/hrbrmstr/overpass for the results from the API. The following two images illustrate that it really is <100m by foot.
Unfortunately i wasnt able to show it graphically on the openstreetmap... I dont know how to get the busstop as startingpoint of a route in the web interface...
Here is the Google-Maps version.
Since you've asked for cinema nodes only in your example query, the result will not include way 42473787. Here's how your query should look like to return ways with amenity=cinema instead:
area[name="Bonn"];
node(area)[highway=bus_stop];
way(around:100)[amenity=cinema];
(._;>;);
out meta;
To get both nodes and ways in one query, simply use a union:
area[name="Bonn"];
node(area)[highway=bus_stop]->.bus_stops;
(
way(around.bus_stops:100)[amenity=cinema];
node(around.bus_stops:100)[amenity=cinema];
);
(._;>;);
out meta;
Try it in overpass turbo!

Resources