gremlin "where" condition how support constant value - gremlin

i want to write a gremlin script,like this:
g.V().out().as('a').[many code].as('b')
.where('a',eq('b').or(eq('a_constant_string'))).by('name')
but a_constant_string is a string constant ,not a vertex or edge
if writing like this,will thrown Exception:
org.apache.tinkerpop.gremlin.driver.exception.ResponseException: Neither the sideEffects, map, nor path has a a_constant_string-key
how to write

When you use where() that way you put the predicate eq() into a mode where it is dealing with labels only so you can't inject a constant in there. In this case, I'd think the easiest thing to do would be to move the "or" outside of the where():
g.V().
out().as('a').as('b').
or(where('a', eq('b')).by('name'),
has('name', 'a_constant_string'))

Related

How does 'as' work when used inside 'where'?

Learning gremlin and looking at examples I see the use of as inside of where steps to match against a previously labeled step.
For example, from official recipes page, a vertex is labeled 'v' with as, later on inside a coalesce it looks for an inE where the outV equals to 'v', but it does so using as again:
gremlin> g.V().has('person','name','vadas').as('v').
V().has('software','name','ripple').
coalesce(__.inE('created').where(outV().as('v')),
addE('created').from('v').property('weight',0.5))
If I were to just read the reference documentation this query would look to me like they are just labeling that outV step as 'v' and nothing more.
This functionality of as doesn't seem to be documented in the reference documentation, and only shows in the examples with no special mention of it.
Does the previous query achieve the same as the following?
gremlin> g.V().has('person','name','vadas').as('v').
V().has('software','name','ripple').
coalesce(__.inE('created').where(outV().where(eq('v'))),
addE('created').from('v').property('weight',0.5))
Is this just a lack of documentation, or is there something I'm missing?
Is saying as has a special meaning inside 'where', correct? Or is there something else to take into account?
Yes - as() has special meaning inside where(). It is described briefly as part of the select()/where() usage (see item 3) and in the match()/where() usage. Basically when you write your query that way you are using where() with its variable binding form and is equivalent to the more direct form that you demonstrate in your second query. Personally, I tend to find the binding form a bit less readable, but that depends on the nature of the filter I guess and sometimes it represents the most clear way to structure the query.
As you observed, an as step is treated differently inside a where step to allow a step label created outside the where step to be treated as a label inside the where step and not a literal string.
There is a writeup here
http://www.kelvinlawrence.net/book/PracticalGremlin.html#patternwhere

gremlin fold() unfold() throwing errors: "Vertex with id 70 was removed" and "The incoming object is not removable"

This query works:
choose(V().hasLabel("user"), V().hasLabel("user").drop())
But is searching 2 times for the vertex "user", I want to optimize it to 1 time, so I changed it for this one:
choose(V().hasLabel("user").fold(), unfold().drop())
If I do that trick multiple times in my query it throws:
Error: ResponseError: Server error: Vertex with id 70 was removed. (500)
I don't understand what that means, maybe fold() does not overwrite previous fold() calls, I don't know.
Is there an alternative to fold() unfold() for this use case? I've tried:
choose(V().hasLabel("user").as("u"), select("u").drop())
but that does not work, it seems .as() don't save anything when is called inside choose()
I also tried:
choose(V().hasLabel("user").store("u"), select("u").drop())
But throws another error I don't understand: The incoming object is not removable
Your first attempt with:
choose(V().hasLabel("user"), V().hasLabel("user").drop())
is not as expensive as you think. The if portion of choose() (i.e. the first child traversal) does not iterate all users. It immediately returns true if one "user" is found". Your then child traversal will iterate all "user" vertices. Also, you don't provide a false value to choose() so in that case, I believe that you will end up calling the drop() traversal for either situation:
gremlin> g.inject(1).choose(V().hasLabel('no-exist'),constant(1))
==>1
gremlin> g.inject(1).choose(V().hasLabel('no-exist'),constant(1),constant(2))
==>2
Of course, I'd wonder why you need to do an if/then here at all because calling V().hasLabel("user").drop() without choose() will remove all "user" vertices found, or if none are found, just do nothing.
For this traversal:
choose(V().hasLabel("user").fold(), unfold().drop())
note that V().hasLabel("user").fold() will always return "true" because you fold() which is a reducing step which will return a List of items in the stream. If the stream is empty you get an empty List and thus choose() will use the true path there. In any event, your unfold() is not unrolling what is returned from the first choose() parameter - it unfolds the same Traverser object handed to the choose() step. You don't have what comes before the choose() so I can't say what that is.
I'm not completely sure but based on your remaining traversal examples, I think you might be misusing choose() in general. You don't seem to have need for an if/then or switch style operation. With Gremlin you don't need to check if something is present in order to remove it and it is in fact cheaper not to do so as mentioned earlier.

How to add a default value for empty traversals in gremlin?

I'm working on a gremlin query that navigates along several edges and eventually produces a String. Depending on the graph content, this traversal may be empty. In case that the traversal ends up being empty, I want to return a default value instead.
Here's what I am currently doing:
GraphTraversal<?, ?> traversal = g.traversal().V().
// ... fairly complex navigation here...
// eventually, we arrive at the target vertex and use its name
.values("name")
// as we don't know if the target vertex is present, lets add a default
.union(
identity(), // if we found something we want to keep it
constant("") // empty string is our default
)
// to make sure that we do not use the default if we have a value...
.order().by(s -> ((String)s).length(), Order.decr)
.limit(1)
This query works, but it is fairly convoluted - all I want is a default if the traversal ends up not finding anything.
Does anybody have a better proposal? My only restriction is that it has to be done within gremlin itself, i.e. the result must be of type GraphTraversal.
You can probably use coalesce() in some way:
gremlin> g.V().has('person','name','marko').coalesce(has('person','age',29),constant('nope'))
==>v[1]
gremlin> g.V().has('person','name','marko').coalesce(has('person','age',231),constant('nope'))
==>nope
If you have more complex logic in mind for determining if something is found or not then consider choose() step.

Why g.V() in gremlin is a GraphTraversal<Vertex, Vertex>?

g.V() is usually used to start a traversal. But since this a startup action, why its begin node is a Vertex?
g is the TraversalSource, by specifying V() you're saying that you are going to start at a set of elements that are of type Vertex, just like by specifying E() would specify starting at a set of elements that are of type Edge http://tinkerpop.apache.org/docs/current/reference/#the-graph-process and http://tinkerpop.apache.org/docs/current/reference/#traversal are pretty clear on how traversals are built up.

Gremlin 'except' usage doesnt seem to work

I am trying to find vertices except for some specific ones and this query below doesnt work:
g.V()
.has('someId')
.except([g.V().has('someId').has('some_other_filter')])
Is this usage of 'except' where I provide it a query within it not correct?
Thanks
You need to iterate your pipe:
g.V()
.has('someId')
.except(g.V().has('someId').has('some_other_filter').toList())
without dumping what's in your except to a list you are actually just passing a pipeline to except which won't ever evaluate against a vertex as true.

Resources