For some reason I'm getting the above error when I try to use addE in my traversal.
const traversal = await g
.V(id)
.fold()
.coalesce(__.unfold(), __.addV().property(t.id, id))
.inE()
.where(__.outV().hasId(bob))
.fold()
.coalesce(__.unfold(), __.addE().from_(__.V(bob)).to(__.V(tweetId))
.next()
Any idea to what's going wrong here? That error message makes no sense to me.
This is on a Neptune server.
You are not supplying an argument to addE(). There is no zero-argument option to that step. You must supply an edge label as an argument either by way of addE(String) or addE(Traversal). If you see that error in the future, it is best to check the javadoc for GraphTraversal or GraphTraversalSource when you see that.
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'))
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.
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.
This is a question to understand the transaction semantics in DSE graph via TinkerPop3 Java API
As I understand, when you have DseSession.executeGraph(String query) is executed in a single transaction.
But what is the mechanism to achieve the same using TinkerPop3 Java API ?
Say I want to add a vertex and then drop a few edges and then add a new vertex etc.,
I tried
g.V("{~label=company, id=12345}").drop().addV("company").property("id", "1").next()
This didn't work as I intended. (Dropping the company and adding one in a single transaction). The first vertex did indeed get deleted, however the new company was never created.
I got below exception
Exception in thread "main" java.util.NoSuchElementException
at com.datastax.dse.graph.internal.DseRemoteTraversal.nextTraverser(DseRemoteTraversal.java:60)
The drop() step "kills" the traverser you are deleting, meaning nothing is returned from drop(). You can see that if you try this:
gremlin> g.V().has('name','marko').drop().next()
java.util.NoSuchElementException
Type ':help' or ':h' for help.
Display stack trace? [yN]
Without a traverser there is nothing to feed forward to your addV() step that follows. There might be a nicer way to do this, but you can work around that problem by using inject() to add a throwaway value as a traverser that will feed into your addV(). In this case, you deleted one thing, so you need to put one traverser back to trigger the single call to addV() thus:
gremlin> g.V().has('name','marko').drop().
......1> inject(1).
......2> addV('person').property('name','stephen').next()
==>v[13]
I also wonder if this is a nice way to do it:
gremlin> g.V().has('name','marko').
......1> union(drop(),
......2> addV('person').property('name','stephen'))
==>v[13]
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.