How to use gremlin vertex value to query an edge property - gremlin

I need to take the value of a vertex and use those individual values to query an edge value and return the edge info.
In the SM node, I have all properties: m1, m2, m3, m4 and v2. I will need v2, to query the id of the v2 node. From there I need to concatenate the properties of m1,m2,m3,m4 and v2 to find the edge or I can find the node with the properties m1,m2, m3, m4 and then find the edge.
Vertext- Edge drawing

Querying an edge by the property of a vertex can be achieved like this:
Added data with below query:
g.addV('vertex').
property(id, 'sm2').
property('m1', 'm1').
property('m2', 'm2').
property('m3', 'm3').
property('m4', 'm4').
property('v2', 'v2').
addV('vertex').
property(id, 'v2').
addE('MRM').to(V('sm2')).iterate()
Used below query to find an incoming edge based on property.
gremlin> g.V('sm2').as('b').
......1> values('v2').as('a').
......2> select('b').
......3> in().as('output').
......4> id().
......5> where(eq('a')).
......6> select('output')
==>v[v2]
However, for concatenating all the properties:
Gremlin does not have very good support for string concatenation like you asked for. Having said that, Gremlin java server should still be able to cater to your requirements provided you also use gremlin java client. You can take a look at The Lambda Solution section in https://tinkerpop.apache.org/docs/current/reference/#gremlin-java-lambda

Related

Gremlin query to check if a value exists in the given external map

I would like to traverse the graph until my node property value exist in the set. Set contains id of the nodes and trivial objects.
The query is like:
public Map<String,Object> getNodes( Long startNodeID, Set<String, TraversedNode> mySet){
return g.withSideEffect("x",mySet).V(startNodeID)
.repeat( ...something )
.choose( ...something )
.until( myProperty is found in the given set )
}
I have tried many things in the until part but couldn't get it. Any suggestions to achieve? It maybe related to values and where keywords.
values("id").where(P.within("x")) doesn't work
Using the air-routes graph as sample data, a simple query can be written that looks for IDs within a provided set, as the query progresses. As mentioned in the comments, it is not 100% clear if this is what you are looking for but perhaps it will help with follow on questions.
gremlin> g.withSideEffect('s',[48,54,62,12]).
......1> V(44).
......2> repeat(out().simplePath()).
......3> until(where(within('s')).by(id).by()).
......4> path().
......5> limit(5)
==>[v[44],v[8],v[48]]
==>[v[44],v[8],v[54]]
==>[v[44],v[8],v[12]]
==>[v[44],v[13],v[12]]
==>[v[44],v[13],v[48]]
It may appear that you should just be able to do until(hasId(within('s'))), but in that case 's' is treated as the literal string "s" and not a symbol representing the set called s. When a predicate is nested inside a where step, as in where(within('s')), Gremlin treats that as a special case and will treat s as the name of something declared earlier.

Merge vertexes and edge between them at the same time in Gremlin

I have a source of data which I read and try to load it into my CosmosDB Graph. Each row that I fetch contains an information about multiple entities (person, software). What I am trying to do here is to:
verify if such a vertex(es) already exist and generate a separate entity for missing entries (person, software)
verify if an edge already exists (between this person and this software)
create an edge between them
I've been making a reference to the following topics:
CosmosDB Graph : “upsert” query pattern, Add edge if not exist using gremlin trying to combine them somehow but without much of a success.
I have tried the following:
g.V().has('person','name','vadas').
fold().coalesce(unfold(), addV('person').property('name','vadas')).as('v').
V().has('software', 'name','ripple').
fold().coalesce(unfold(), addV('software').property('name','ripple')).
coalesce(__.inE('created').where(outV().as('v')), addE('created').from('v'))
but it only creates the vertices without the edge between them.
I am also wondering if there's a bit more common approach to kind of:
1. Upsert entity A and keep a reference to it
2. Upsert entity B and keep a reference to it
3. Upsert entity C and keep a reference to it
....
1. Upsert edge between A and B
2. Upsert edge between A and C
You have a reducing barrier step (i.e. fold()) that comes between you step label of "v" and where you try to retrieve it in where(). Note what happens more explicitly in the example below:
gremlin> g.V().has('person','name','vadas').
......1> fold().coalesce(unfold(), addV('person').property('name','vadas')).as('v').
......2> V().has('software', 'name','ripple').
......3> fold()
==>[v[5]]
gremlin> g.V().has('person','name','vadas').
......1> fold().coalesce(unfold(), addV('person').property('name','vadas')).as('v').
......2> V().has('software', 'name','ripple').
......3> fold().select('v')
gremlin>
As you can see, you can't select('v'). The path history for that traverser is gone. The history is lost because you've reduced the stream from many traversers to one so "v" loses context in that merge.
When this sort of thing happens you typically just need to re-write your traversal a bit. I might do something like this in your case as it incurs the least change and maintains readability nicely:
gremlin> g.V().has('person','name','vadas').
......1> fold().
......2> coalesce(unfold(), addV('person').property('name','vadas')).
......3> V().has('software', 'name','ripple').
......4> fold().
......5> coalesce(unfold(), addV('software').property('name','ripple')).
......6> coalesce(__.inE('created').where(outV().has('person','name','vadas')),
......7> addE('created').from(V().has('person','name','vadas')))
==>e[24][2-created->5]

Is it possible to read some value and then use this value in an update?

The environment is gremlin (cosmos, specifically).
I would like to migrate a value from Vertex A to Vertex B. The vertices are connected by an edge, e.g.
A (Name: 'x') -[connected]-> B
Is it possible to read the 'Name' property in A and write it to B in a single query?
With Gremlin you can label a step and then refer back to it later in the traversal with select():
gremlin> g.addV().property('name','someone').as('a').
......1> addV().property('name','').as('b').
......2> addE('connected').from('a').to('b').iterate()
gremlin> g.V().has('name','someone').as('a').
......1> out('connected').
......2> property('name',select('a').values('name')).iterate()
gremlin> g.V().valueMap(true)
==>[id:0,name:[someone],label:vertex]
==>[id:2,name:[someone],label:vertex]
Please consider reading about traversal induced values for some additional examples.

TinkerPop: Filter by Edge not connected with an Edge

Sample database: TinkerPop Modern
Objective: Find People who have not developed a Software.
ie. Vertex type "Person" that is not directly connected to Vertex type "Software"
Person connected to Software [Works]
g.V().hasLabel("Person").as("from")
.project("title", "node")
.by(select("from").unfold().values("name").fold())
.by(select("from").unfold().label().fold())
Find Person not connected to Software [Does not work]
g.V().hasLabel("Person").as("from")
.filter(both().not(hasLabel("Software")))
.project("title", "node")
.by(select("from").unfold().values("name").fold())
.by(select("from").unfold().label().fold())
I believe its ignoring an edge that does not satisfy the condition, but does not skip the Vertex.
Tried to do a loop but did not find an example for it.
Cypher Query equivalent (for reference only): MATCH (n:People) WHERE NOT (n)--(:Software) RETURN n
Sample database:
I believe that you just need to change your filter criteria:
gremlin> g.V().hasLabel('person').
......1> filter(__.not(outE('created'))).
......2> project("title", "node").
......3> by('name').
......4> by(label)
==>[title:vadas,node:person]
As you can see, you also don't need to select back to that as() step for any reason - you already have that vertex as the current traverser in project().

Gremlin, find vertices with similar relationships

I'm after getting some gremlin together which would, for a given vertex, find other vertices which share the same or similar relationship.
So for example, imagine a graph of Persons and these Persons have relationships to other entities like subjects and grade. Lets say I select a Person, lets call them Dave. He is linked to English and History and is a grade B.
Dave -STUDIES-> English
Dave -STUDIES-> History
Dave -IS_IN -> B
How would find other Persons who shared these relationships using Gremlin?
I've got as far as
g.V('Dave').out()
Find everything Dave is related to
How can I use this to find other Persons who share some or all of the same relationships as Dave?
(i've done this in neo4j and its quite straight forward
match ((p1:Person{name:'Dave'})-[r]->(n)),((p2:Person)-[s]->(n))
return distinct p1.name,p2.name, count(p2.name)
order by count(p2.name) desc
)
thanks !
When asking questions about Gremlin it is always helpful to include a script that creates your sample graph - for example:
g.addV('person').property('name','dave').as('d').
addV('person').property('name','rick').as('r').
addV('person').property('name','mavis').as('m').
addV('person').property('name','larry').as('l').
addV('course').property('name','english').as('e').
addV('course').property('name','history').as('h').
addV('grade').property('name','b').as('b').
addE('studies').from('d').to('e').
addE('studies').from('r').to('e').
addE('studies').from('m').to('h').
addE('studies').from('d').to('h').
addE('studies').from('r').to('h').
addE('isIn').from('l').to('b').
addE('isIn').from('d').to('b').iterate()
Here's a fairly direct way to get your answer:
gremlin> g.V().has('person','name','dave').as('d').
......1> out('studies','isIn').
......2> in('studies','isIn').
......3> where(neq('d')).
......4> dedup().
......5> values('name')
==>mavis
==>rick
==>larry
First you find "dave", label that step as "d" so that you can reference its contents later, then traverse out() over the edges you want to match on and then back in() on those same edges. At this point, you're back at "person" vertices who are in the same "grades" and "courses" as "dave", but you want to exclude "dave" vertices from the output so you use that where() step. You might have duplicates if a "person" shares more than one "course" or "grade" with "dave" so you must dedup().
That's the basic algorithm, but you can get more advanced. Maybe you want to sort those "matches" by the number of things that each "person" has in common with "dave":
gremlin> g.V().has('person','name','dave').as('d').
......1> out('studies','isIn').
......2> in('studies','isIn').
......3> where(neq('d')).
......4> groupCount().
......5> by('name').
......6> order(local).
......7> by(values, decr)
==>[rick:2,mavis:1,larry:1]
"rick" has two "matches" (i.e. shares "english" and "history" classes) with "dave" and thus has the highest ranking. Note that the use of local in the order() step is important in that it means to sort within the current traverser (i.e. the Map of name/count) - without that designation the sort would be applied to the objects in the traversal stream itself.

Resources