Create Inner Gremlin query using edge information - graph

I'm trying to create user Notification whenever any user comments on user's post.
i'm using following gremlin query -
g.v(512).outE('Notification').order{it.b.PostedDate <=> it.a.PostedDate}[0..3].transform{ [notificationInfo:it,postInfo:it.inV]}
and am getting following result -
Am getting NotificationInitiatedByVertexId value in edge. how can I use that vertex id (ie. NotificationInitiatedByVertexId: 1280) to get information about the vertex in the same query result.

I would suggest trying to add it to the transform statement you already have:
g.v(512).outE('Notification').order{it.b.PostedDate <=> it.a.PostedDate}[0..3].transform{ [notificationInfo:it,postInfo:it.inV,notifiedV:g.v(it.NotificationInitiatedByVertexId)]}

Related

NebulaGraph Database: How to get all the vertices of each tag?

I want to get all the vertices of each tag in the Nebula Graph Database.
I tried using fetch prop on player * yield properties(vertex) to get the results, but this was not possible.
(root#nebula) [basketballplayer]> fetch prop on player * yield properties(vertex)
[ERROR (-1004)]: SyntaxError: syntax error near `* yield '
And I tried using neo4j statement match (v:player) return v, but it didn't work either.
root#nebula) [basketballplayer]> match (v:player) return v
[ERROR (-1005)]: Scan vertices or edges need to specify a limit number, or limit number can not push down.
Who can teach me how to use the Nebula Graph database correctly?
By design, the per tag/edge type scan(just like a tabular DBMS data scan) was chosen to be prohibited by default.
Due to the data was stored in NebulaGraph in a more linked/graph way(think of a graph traversal, which started from known nodes and then expand multiple hops along with the edges/relationships). Thus enabling a non-graph scan of data in a distributed graph database like NebulaGraph is costly.
To enable such queries, an index needs to be explicitly created before that 0 or LIMIT sample clause [1] was used(could also avoid full scan).
[1]: example of query(need index for starting node) with LIMIT clause
MATCH (v:player) RETURN v LIMIT 100
Note: the index is only related to the starting node seeking of the query pattern.

How to return only the id of a vertex in Cosmos Graph

I am importing data from SQL Server to Cosmos Gremlin Graph. During the process, I need to search for a vertex by its old id, as the new id is needed to create an edge. I only want the id not all the other properties.
I found the answer.
You can use the SubmitWithSingleResultAsync( query ); method with a query like g.V().has('elementTypeId','1').has('importId',123456).properties('id').value()

Add Additional Property to Neptune DB

I am trying to add additional property called "insert_date" to the existing vertices and edges. I tried
g.V().setProperty('insert_date',datetime('2020-10-06'))
Error:
{
"requestId": "33cf8df5-3cbe-41ac-b650-5752debec04d",
"code": "MalformedQueryException",
"detailedMessage": "Query parsing failed at line 1, character position at 10, error message : token recognition error at: 'rop'"
}
I am trying the above command from Neptune Notebook.
It just adds new vertices with insert_date property. But I did not find the way to alter existing vertices or edges.
Please suggest if this is possible. As I want to implement delta extraction so that I can extract only new vertices or edges every time I run ETL.
Thanks
To add a property to an existing vertex in Gremlin you use the property() step. For example, if you wanted to add a property insert_date to a vertex with the id of A you would use the following statement:
g.V('A').property('insert_date', '2020-10-06')
The property() step will add or update the specified property to the new value. This will occur for all the current elements being passed in. For example, if you only wanted to update the elements that did not have an insert_date property you could do this via:
g.V().hasNot('insert_date').property('insert_date', '2020-10-06')
In each of these example the property will be added as part of an array of values. If you want to set the property to only contain a single value then you can use the property() step overload that takes the cardinality like this:
g.V('A').property(Cardinality.single, 'insert_date', '2020-10-06')
One thing to note in the code you have listed above. While Neptune does support the datetime() function for string-based queries, if you are not using a GLV then you will need to create this value and pass in a Native Date/Time as described here.
Below Command worked to add additional properties to existing Graph.
g.V().property("insert_date","2020-01-01 00:00:00")

Create Vertex only if "from" and "to" vertex exists

I want to create 1000+ Edges in a single query.
Currently, I am using the AWS Neptune database and gremlin.net for creating it.
The issue I am facing is related to the speed. It took huge time because of HTTP requests.
So I am planning to combine all of my queries in a string and executing in a single shot.
_g.AddE("allow").From(_g.V().HasLabel('person').Has('name', 'name1')).To(_g.V().HasLabel('phone').Where(__.Out().Has('sensor', 'nfc'))).Next();
There are chances that the "To" (target) Vertex may not be available in the database. When it is the case this query fails as well. So I had to apply a check if that vertex exists before executing this query using hasNext().
So as of now its working fine, but when I am thinking of combining all 1000+ edge creation at once, is it possible to write a query which doesn't break if "To" (target) Vertex not found?
You should look at using the Element Existence pattern for each vertex as shown in the TinkerPop Recipes.
In your example you would replace this section of your query:
_g.V().HasLabel('person').Has('name', 'name1')
with something like this (I don't have a .NET environment to test the syntax):
__.V().Has('person', 'name', 'name1').Fold().
coalesce(__.Unfold(), __.AddV('person').Property('name', 'name1')
This will act as an Upsert and either return the existing vertex or add a new one with the name property. This same pattern can then be used on your To step to ensure that it exists before the edge is created as well.

Tinkerpop Gremlin group by key and get latest

I am creating 2 users(uid=1 & uid=2) with 2 versions each.
g.addV('user1').property('uid',1).property('version',1)
.addV('user1').property('uid',1).property('version',2)
.addV('user1').property('uid',2).property('version',1)
.addV('user1').property('uid',2).property('version',2)
I want to get the latest version from each uid, I am using the uid as a groupBy key and getting the latest as shown
g.V().hasLabel('user1')
.group().by('uid').by(fold().order(Scope.local).by('version', Order.desc).unfold().limit(1)) //GraphTraversal<Vertex,Map<Object, Object>>
.flatmap(t -> t.get().values().iterator()) // convert to GraphTraversal<Vertex, Vertex>
//traverse out and get the path
.out('friend').path().by(elementMap())
Is the best approach for this requirement?
What would be the gremlin preferred way to convert the Map to a Vertex inside the flatmap rather than using the lambda? Suppose I want to add further steps after this.
Appreciate any help!
The group step has two modes. Without a label it acts as a barrier but with a label it acts as a side effect. You can have results flow through a group using your data as follows.
gremlin> g.V().group('x').by('uid').by(values('version').max())
==>v[42306]
==>v[42309]
==>v[42312]
==>v[42315]
==>v[42318]
gremlin> g.V().group('x').by('uid').by(values('version').max()).cap('x')
==>[1:2,2:2]
You can add more traversal steps of course before you decide what you want to do with the group. Such as:
g.V().group('x').by('uid').by(values('version').max())out()...

Resources