Gremlin - how to ensure one vertex only have one inbound edge? - gremlin

I have person vertex and book vertex connected by owns edge (aka person=> owns => book). How can I ensure one book can only be owned by one person? In other words, I need a Gremlin query like addE('owns').from(person_1).to(book_1) only if the vertex book_1 has no inbound edge.

This pattern is described in the "Element Existence" recipe and follows the standard fold()/coalesce()/unfold() pattern. Basically, you would so something like:
g.V('book_1_id').as('book_1').
V('person_1_id').as('person_1').
coalesce(outE('owns').where(outV().as('book_1')),
addE('owns').from(`person_1`).to(`book_1`))
If you are using TinkerPop 3.6.x or later you might try using the mergeE() step:
g.mergeE([(from):'book_id_1',(to):'book_id_1',(label):'owns'])

Related

Get nodes adjacent to child node in Gremlin

I'm fairly new to Gremlin and I'm trying to query a graph starting at my vertex Customer, which is related to various nodes amongst which is the Account node. And so, I want to retrieve all nodes related to the Customer node + all nodes related to the Account node connected to it.
As you can see in the image, my Customer node is related to the account node via the has_account edge. I would like to get all the nodes adjacent to that account node.
Customer node
As I said, I'm fairly new to neptune so what I've tried aside from the most basic visualizations is:
g.V('id').outE().inV().outE().inV().path()
And that gives me the nodes adjacent to the Account node but ommits the other adjacent nodes to the Customer node. I've also tried some other groupings and mappings but I can't seem to make it work.
In the query you wrote above, you are starting out a vertex id and then traversing to all of its connections (the first outE().inV(), and then the connections of the connections (the second outE().inV()). If a connection does not have any connections, then it will be filtered out.
If you would like to return both the 1st and optionally 2nd connections, then I would look at using the optional() step for the 2nd+ level connections that may or may not exist like this:
g.V('id').outE().inV().optional(outE().inV()).path()

OpenCypher - Get all nodes that not connect to the center of the graph

I have a graph on Neptune and I used OpenCypher to query on it.
At the middle of the graph I have a big connected nodes,
at the edges you can see that I have some single nodes/ nodes that connected only to 1-5 other nodes. (see on the picture)
I want to get all of them, there is an option to do so?
I tried to think about options like take a random Id from the center and check all the nodes that don't have a path from them to this node, or maybe say get a table with all nodes and number of connected nodes to them, and ask for all nodes that not contain more than 10 nodes connected
but I didn't find a way to write this query,
Must to know that opencypher on Neptune not contains all the magic keys like 'all' predicate function, so need to find a way with the functions that neptune support
Ideally, you would want to run Weakly Connected Components algorithm to identify the largest component and then return all nodes that are not part of it. It seems that Neptune doesn't support that algorithm out-of-the-box, but you could implement it with gremlin as discussed in another SO question: Find largest connected components AWS Neptune

Is it possible to change edges between vertices in gremlin

I have a scenario where I may need to update the from/to vertex of an already existing edge. I dont think there is any mechanism in gremlin to do so. So, what would be an ideal approach to achieve such functionality? What I can think of is -
Assuming To Vertex changes over time in an edge, Make sure the Edge ID is unique something like "From-Relationshipname"
While adding new edges check if Edge is already present then drop old Edge using the EdgeId and create a new one
Is it an efficient way?
Check the following recipe published in Gremlin docs for moving an edge.
The "marko" vertex contains a "knows" edge to the "vadas" vertex. The following code shows how to "move" that edge to the "peter" vertex in a single traversal:
g.V().has('name','marko').as('a').
outE('knows').as('e1').filter(inV().has('name','vadas')).
V().has('name','peter').
addE('knows').from('a').as('e2').
sideEffect(select('e1').properties().
unfold().as('p').
select('e2').
property(select('p').key(), select('p').value())).
select('e1').drop()
Source: https://tinkerpop.apache.org/docs/current/recipes/#edge-move

Gremlin query to traverse nodes and edges based on user permissions (stored as node/edge property) [duplicate]

We are stamping user permission as a property (of SET cardinality) on each nodes and edges. Wondering what is best way to apply the has step on all the visited nodes/edges for a given traversal gremlin query.
like a very simple travarsal query:
// Flights from London Heathrow (LHR) to airports in the USA
g.V().has('code','LHR').out('route').has('country','US').values('code')
add has('permission', 'team1') to all the visited vertices and edges while traversal using the above query.
There are two approaches you may consider.
Write a custom TraversalStrategy
Develop a Gremlin DSL
For a TraversalStrategy you would develop one similar to SubgraphStrategy or PartitionStrategy which would take your user permissions on construction and then automatically inject the necessary has() steps after out() / in() sorts of steps. The drawback here is that your TraversalStrategy must be written in a JVM language and if using Gremlin Server must be installed on the server. If you intend to configure this TraversalStrategy from the client-side in any way you would need to build custom serializers to make that possible.
For a DSL you would create new navigational steps for out() / in() sorts of steps and they would insert the appropriate combination of navigation step and has() step. The DSL approach is nice because you could write it in any programming language and it would work, but it doesn't allow server-side configuration and you must always ensure clients use the DSL when querying the graph.
We are stamping user permission as a property (of SET cardinality) on each nodes and edges.
As a final note, by "SET cardinality" I assume that you mean multi-properties. Edges don't allow for those so you would only be able to stamp such a property on vertices.

ArangoDB anonymous graph traversal

I am planing to use ArangoDB and I am faced with a problem I don't know how to solve. I would like to do simple traversals but in my case but there are two requirements that I don't know how to solve:
I will not know in advance the type of vertices than an edge will connect to. I want to be able to connect edge of one type to any vertex on any side.
For one vertex, I want to retrieve all connected vertices (depth 1) no matter the edge type.
For the requirement 1, an example would be a Tag vertex (to tag some entity with some information) and I want to be able to tag any vertex using i.e. HasTag edge in a named graph. From what I currently see is that I need to define the "From" collections ("To" collection is the Tag collection) and this is limited to 10 collections. Since I could have 100 or more From collections I don't see how to solve this with named graphs.
Option would be to use anonymous graphs but then I have a problem in the second requirement. I also want to have an option, when given a vertex, to find all connected vertices (depth = 1) no matter the type of an edge. In an anonymous graph I would need to specify all of the edge collections in a query and again, there could be 100 or more of them. I don't know if there is a limit to this number but I would assume there is one - maybe I'm mistaken since I haven't yet tried it out.
Has anyone any idea how to solve this with ArrangoDB? I really like the database but I would like it to be more "typeless", that is, that I wouldn't have to define the type of vertex collection an edge can connect to.
Best regards
Tomaz
You can have more than 10 vertex collections in a named graph. The limitation of 10 only exists in the webUI. Creating the named graph over the ArangoShell or the server console will work.

Resources