How to set default values or return null value for a property which is missing in the graph and is been queried in the project() step - gremlin

Referring to this previously asked question:
Default value when property is missing with project() step in Gremlin?
Is there a more efficient way to do the same thing or preferably returning "null" in the latest gremlin version as each coalesce step takes 2 additional traversals?

Gremlin will not have a notion of a null traverser until 3.5.0 is released (there is no schedule for release at this time). Here are some of examples of what to expect from 3.5.0:
gremlin> g = TinkerGraph.open().traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> g.addV('person').property('name','allen')
==>v[0]
gremlin> g.V().has('person','name','allen').project('name','age').by('name').by('age')
==>[name:allen,age:null]
gremlin> g.V().has('person','name','allen').elementMap()
==>[id:0,label:person,name:allen]
gremlin> g.V().has('person','name','allen').elementMap('name','age')
==>[id:0,label:person,name:allen]
gremlin> g.V().has('person','name','allen').values('name','age')
==>allen
gremlin> g.V().has('person','name','allen').union(values('name'),values('age'))
==>allen
gremlin> g.V().has('person','name','allen').union(values('name'),coalesce(values('age'),constant(null)))
==>allen
==>null
There shouldn't be much loss in efficiency for using coalesce() even if you must use many of them. The cost of constant() is not an issue and values(String) assuming that's all you're doing will compile to a fast TokenTraversal. I suppose the big loss is having to type a lot. I'm not aware of any graph databases (maybe sqlg since it's based on relational backends?) that support default values as most don't have notion of a schema.

Related

is it possible to declare a variable with gremlin node values and later traverse using the variable

I wonder if gremlin can handle a data structure graph where you can save the reference to the node in a variable and later use it to traverse neighboring nodes.
node1= g.V(1)
node1.out('knows')
There are two confusing aspects here:
A Traversal is a kind of Iterator that can only be used once
The Gremlin Console iterates each Traversal for a significant (configurable) number of times
The second aspect can be prevented with the code example below. The first aspect makes the answer to your question a practical "no". Of course you can code some kind of abstraction that fulfills your needs yourself.
gremlin> node1 = g.V(1); null
==>null
gremlin> node1.class
==>class org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal
gremlin> contacts = node1.out('knows'); null
==>null
gremlin> contacts
==>v[2]
==>v[4]
gremlin> contacts
gremlin>

How to sort elements in subquery locally in gremlin?

Let's assume we have a graph of persons, with properties
name (String)
age (int)
... and friend edges in between some of them. Let's further assume we have a complex gremlin query which eventually produces person vertices.
Now, for each of the resulting persons, we want to find the three oldest friends in a subquery.
This is the rough query structure:
g.traversal.V()
// complex filtering and navigation here, produces person vertices
.flatMap(
__.out(friend)
.order().by("age", desc)
.limit(3)
)
// complex query continues with the three oldest friends per input vertex here
The problem with this query is that the order().by(...) step is global. I get three persons in total for all person vertices which enter the flatMap(...).
What I would like to receive is (up to) three persons per vertex entering the flatMap(...) step.
How would you do that in gremlin? I've read that there is "local" scoping of sorts, but I was unable to make it work.
I would expect your traversal to work as you would wish it to. See my examples with TinkerGraph and the "modern" toy graph:
gremlin> g.V().hasLabel('person').flatMap(out().order().by(id))
==>v[2]
==>v[3]
==>v[4]
==>v[3]
==>v[5]
==>v[3]
gremlin> g.V().hasLabel('person').flatMap(out().order().by(id).limit(1))
==>v[2]
==>v[3]
==>v[3]
gremlin> g.V().hasLabel('person').flatMap(out().order().by(id).limit(2))
==>v[2]
==>v[3]
==>v[3]
==>v[5]
==>v[3]
Or perhaps easier to see in action with just map():
gremlin> g.V().hasLabel('person').map(out().order().by(id).fold())
==>[v[2],v[3],v[4]]
==>[]
==>[v[3],v[5]]
==>[v[3]]
gremlin> g.V().hasLabel('person').map(out().order().by(id).limit(1).fold())
==>[v[2]]
==>[]
==>[v[3]]
==>[v[3]]
gremlin> g.V().hasLabel('person').map(out().order().by(id).limit(2).fold())
==>[v[2],v[3]]
==>[]
==>[v[3],v[5]]
==>[v[3]]
Perhaps there is something in your data that you are not expecting? If the problem persists maybe you could debug with map() as I showed above and see what's being returned before the lists are flattened? If all else fails, please update your question with a script that provides some sample data and a Gremlin Console session demonstrating the failure with that data.

Cosmos DB Search Query which takes Vertex values with any character

I am using Azure cosmos Db, In cosmosDB i have so many vertexes, each vertex has properties in key value form. I want to find any gremlin query which checks Vertex values which start with any character.
Filter Query is there but for azure filter query is not supported, so is there any other Gremlin query which takes Vertex properties values which start with any character?
Although I never tried CosmosDB myself, I have to disagree with John. According to CosmosDB's docs, any range query on any property is processed from the index. Hence, if you want to find all person vertices that have a name property that starts with a, you can do:
g.V().has("person", "name", between("a", "b"))`
A concrete example over TinkerPop's toy graph:
gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> g.V().has("name", between("m", "n")).valueMap()
==>[name:[marko], age:[29]]
gremlin> g.V().has("name", between("j", "k")).valueMap()
==>[name:[josh], age:[32]]
gremlin> g.V().has("name", between("j", "n")).valueMap()
==>[name:[marko], age:[29]]
==>[name:[lop], lang:[java]]
==>[name:[josh], age:[32]]
“start with any character” requires Full-Text search, yet Cosmos DB does not support it per their documentation https://learn.microsoft.com/en-us/azure/cosmos-db/gremlin-support#gremlin-steps .
JanusGraph support Full-Text search or String search, for example:
g.V().has('bookname', textPrefix('uni'))
For more info please refer to http://docs.janusgraph.org/latest/index-parameters.html#text-search

How to merge Two Vertex details and Edge Properties details Together in a single gremlin query

How to merge Two Vertex details and Edge Properties details Together in a single gremlin query.
I'm having two Vertices :
UserInfo vertex
PostInfo vertex
EdgeInfo Between them
With Gremlin Query : g.v(2569472).out('_label','WallPost')[0..1]
I'm getting UserPost Vertex details , i want to add UserVertex detail in the response (i.e gender ) and Edge property detail in the response (i.e EdgeMessage)
I'm trying to compare sql equivalent innerjoin operation with gremlin from sql2gremlin but i'm not able to get the desired result.
SQL2Gremlin is written for TinkerPop 3, you're still using TinkerPop 2 (which is a lot more complicated IMO). Anyway, here's how you would do it in TP2:
gremlin> g = TinkerGraphFactory.createTinkerGraph()
==>tinkergraph[vertices:6 edges:6]
gremlin> g.v(1).outE("knows")
==>e[7][1-knows->2]
==>e[8][1-knows->4]
gremlin> g.v(1).outE("knows").inV().retain([g.v(4)])
==>v[4]
gremlin> g.v(1).as("x").outE("knows").as("y").inV().retain([g.v(4)]).select(["x","y"]) {it.map()} {it.weight}
==>[x:{name=marko, age=29}, y:1.0]

Tinkerpop - how do I find a node in the graph?

I can't seem to find a specific node in the graph without traversing the whole thing. Is there something I'm missing?
I'm using tinkerpop blueprints.
Orientdb gives some sort of unsemantic id to a node such as '#8:1' - how do I find this without knowing the id? vertex has a property like 'user=jason' that will identify it.
I'm thinking I'll just use redis to store the user/location pair or otherwise use a supernode (no thanks)
Blueprints has the notion of key indices.
https://github.com/tinkerpop/blueprints/wiki/Graph-Indices
Given your example, define a key index for "user", then query it with the key index. Here's an example using OrientDB from a Gremlin prompt:
gremlin> g = new OrientGraph("memory://graph")
==>orientgraph[memory://graph]
gremlin> g.createKeyIndex("user", Vertex.class)
==>null
gremlin> g.addVertex([user:"Jason"])
==>v[#8:-3]
gremlin> g.addVertex([user:"Rick"])
==>v[#8:-4]
gremlin> g.stopTransaction(SUCCESS)
==>null
gremlin> g.V('user','Jason')
==>v[#8:1]

Resources