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.
Related
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'))
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
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.
I recognized that (insert/delete)-XQueries executed with the BaseX client always returning an empty string. I find this very confusing or unintuitive.
Is there a way to find out if the query was "successful" without querying the database again (and using potentially buggy "transitive" logic like "if I deleted a node, there must be 'oldNodeCount-1' nodes in the XML")?
XQuery Update statements do not return anything -- that's how they are defined. But you're not the only one who does not like those restrictions, and BaseX added two ways around this limitation:
Returning Results
By default, it is not possible to mix different types of expressions
in a query result. The outermost expression of a query must either be
a collection of updating or non-updating expressions. But there are
two ways out:
The BaseX-specific update:output() function bridges this gap: it caches the results of its arguments at runtime and returns them after
all updates have been processed. The following example performs an
update and returns a success message:
update:output("Update successful."), insert node <c/> into doc('factbook')/mondial
With the MIXUPDATES option, all updating constraints will be turned off. Returned nodes will be copied before they are modified by
updating expressions. An error is raised if items are returned within
a transform expression.
If you want to modify nodes in main memory, you can use the transform
expression.
The transform expression will not help you, as you seem to modify the data on disk. Enabling MIXUPDATES allows you to both update the document and return something at the same time, for example running something like
let $node := <c/>
return ($node, insert node $node into doc('factbook')/mondial)
MIXUPDATES allows you to return something which can be further processed. Results are copied before being returned, if you run multiple updates operations and do not get the expected results, make sure you got the concept of the pending update list.
The db:output() function intentionally breaks its interface contract: it is defined to be an updating function (not having any output), but at the same time it prints some information to the query info. You cannot further process these results, but the output can help you debugging some issues.
Pending Update List
Both ways, you will not be able to have an immediate result from the update, you have to add something on your own -- and be aware updates are not visible until the pending update list is applied, ie. after the query finished.
Compatibility
Obviously, these options are BaseX-specific. If you strongly require compatible and standard XQuery, you cannot use these expressions.
I recognized that (insert/delete)-XQueries executed with the BaseX client always returning an empty string. I find this very confusing or unintuitive.
Is there a way to find out if the query was "successful" without querying the database again (and using potentially buggy "transitive" logic like "if I deleted a node, there must be 'oldNodeCount-1' nodes in the XML")?
XQuery Update statements do not return anything -- that's how they are defined. But you're not the only one who does not like those restrictions, and BaseX added two ways around this limitation:
Returning Results
By default, it is not possible to mix different types of expressions
in a query result. The outermost expression of a query must either be
a collection of updating or non-updating expressions. But there are
two ways out:
The BaseX-specific update:output() function bridges this gap: it caches the results of its arguments at runtime and returns them after
all updates have been processed. The following example performs an
update and returns a success message:
update:output("Update successful."), insert node <c/> into doc('factbook')/mondial
With the MIXUPDATES option, all updating constraints will be turned off. Returned nodes will be copied before they are modified by
updating expressions. An error is raised if items are returned within
a transform expression.
If you want to modify nodes in main memory, you can use the transform
expression.
The transform expression will not help you, as you seem to modify the data on disk. Enabling MIXUPDATES allows you to both update the document and return something at the same time, for example running something like
let $node := <c/>
return ($node, insert node $node into doc('factbook')/mondial)
MIXUPDATES allows you to return something which can be further processed. Results are copied before being returned, if you run multiple updates operations and do not get the expected results, make sure you got the concept of the pending update list.
The db:output() function intentionally breaks its interface contract: it is defined to be an updating function (not having any output), but at the same time it prints some information to the query info. You cannot further process these results, but the output can help you debugging some issues.
Pending Update List
Both ways, you will not be able to have an immediate result from the update, you have to add something on your own -- and be aware updates are not visible until the pending update list is applied, ie. after the query finished.
Compatibility
Obviously, these options are BaseX-specific. If you strongly require compatible and standard XQuery, you cannot use these expressions.