Regarding understanding the necessity of Graph Creation in ArangoDB - graph

I don't understand the necessity of creating graphs in ArangoDB.
For example, refer the below AQLs,
// Paths between 2 vertices
FOR p IN TRAVERSAL(person, knows, "person/person3", "outbound", {
paths: true, filterVertices: [{_id: "person/person2"}],
vertexFilterMethod: ["exclude"]}) RETURN p.path.vertices[*].name
//All connected Vertices for a given Vertex..**
FOR p IN PATHS(person, knows, "outbound")
FILTER p.source._id == "person/person5"
RETURN p.vertices[*].name
The above two queries are clearly related to Graphs...but you no need to create a graph to make them work.
Why and when should I create a graph?
What advantages will I get if I create a graph?

Creating or registering a 'graph' in ArangoDB is optional. Its purpose is to maintain graph persistency during modifications.
You can use Document features and combinations of graph traversals on the collections without referencing the graph.
However, one main purpose of the graph definition above is to use it during modifying edges or vertices. A Vertex document in a vertex collection may be referenced from several edge documents in several edge collections, with these edge collections in term belonging to several graphs.
When you now remove a vertex via a graph API, all these graph definitions are queried whether they permit edges pointing into this very special vertex collection. Subsequentially all edges in all possible edge collections are searched and removed. All this is done with transactional security.
By doing this, the mentioned graph persistency can be maintained. Graph persistency means that you don't have dangling edges that are pointing to a previously removed vertex.
Plesae note that you should rather use pattern matching traversals; One could rephrase
FOR p IN TRAVERSAL(person, knows, "person/person3", "outbound", {
paths: true, filterVertices: [{_id: "person/person2"}],
vertexFilterMethod: ["exclude"]}) RETURN p.path.vertices[*].name
like this using the more modern pattern matching:
FOR v, e, p IN 1..20 OUTBOUND "person/person3"
FILTER v._ID != "person/person2"
RETURN p.vertices[*].name

Related

Given a set of nodes of a strongly connected graph as input can we get subgraph and path traversal between them

I have this requirement in ArangoDB AQL: I have a graph created with Document collection for node and Edge collection for directed edge relation.
I want to input a subset of list of nodes as input to AQL query and get all the node traversals /sub graph as the output.
How to achieve this from AQL?
I want to know the relation between given nodes in that way. Please comment if more details are needed.
I know below query now
FOR v IN 1..1 INBOUND[or OUTBOUND] 'Collection/_key' EdgeCollection
OPTIONS {bfs: true}
RETURN v
I'd recommend reviewing the queries on the ArangoDB sample page where it shows how it performs graph queries, and how to review the results.
In your sample query above you are only returning v (vertex information) as in FOR v IN.
That returns only the last vertex from every path that the query returns, it doesn't return edge or path information.
For that you need to test with FOR v, e, p IN and it will return extra information about the last edge (e), and the path (p) it took.
In particular look at the results of p as it contains a JSON object that holds path information, which is a collection of vertices and edges.
By iterating through that data you should be able to extract the information you require.
AQL gives you many tools to aggregate, group, filter, de-duplicate, and reduce data sets, so make sure you look at the wider language functions and practice building more complex queries.

DSE graph same vertex part of two vertex labels?

In my case there are two vertex labels : User, Seller.
Register user create new vertex using custom vertex id :
g.addV(label,'User', 'id', '123456789', 'name', 'User1').next();
When user login and if he register a new business then he become Seller.
Now i want same vertex id to be part of Seller label which is not acheivable.
If i create new vertex with seller label then whole graph(hasmobile, hasaddress) stored against user vertex will not be accessible with seller vertex.
Is there way to acheive this in DSE graph ?
The semantics of TinkerPop and DSE Graph (as well as most graph implementations - with Neo4j the only exception I can think of) do not allow a vertex to have multiple labels. You might think of the reason as being why you wouldn't have a row exist in multiple tables in a SQL database.
There are multiple ways you could resolve this. Make a "Person" vertex (instead of "User" or "Seller") then:
Infer whether they are a "User" or "Seller" from some aspect of the data related to them. Perhaps that is done with an "isSeller" or "isUser" property. Then you would query for sellers with
g.V().hasLabel('Person').has('isSeller',true)
Create a sub-type system where you connect your "Person" vertex to a "User" vertex or "Seller" vertex. Then you can then do stuff like "find a user only if they are a seller" with
g.V().hasLabel('User').has('someid','12345').
filter(__.in('isAPerson').out('isASeller'))

arangodb aql effectively tarversing from startvertex through the endvertex and find connection between them

i'm very new to graph concept and arangodb. i plan to using both of them in a project which related to communication analysis. i have set the data to fit the need in arangodb with one document collection named object and one edge collection named object_routing
in my object the data structure is as follow
{
"img": "assets/img/default_message.png",
"label": "some label",
"obj_id": "45a92a7344ee4f758841b5466c010ed9",
"type": "message"
}
...
{
"img": "assets/img/default_person.png",
"label": "some label",
"obj_id": "45a92a7344ee4f758841b5466c01111",
"type": "user"
}
in my object_routing the data structure is as follow
{
"message_id": "no_data",
"source": "45a92a7344ee4f758841b5466c010ed9",
"target": "45a92a7344ee4f758841b5466c01111",
"type": "has_contacted"
}
with _from : object/45a92a7344ee4f758841b5466c010ed9 and _to : object/45a92a7344ee4f758841b5466c01111
the sum of data for object is 23k and for object_routing is 127k.
my question is, how can i effectively traversing from start vertex through the end vertex, so that i can presumably get all the connected vertex and its edge and its children and so on between them untill there is nothing to traverse again?
i'm afraid my question is not clear enough and my understanding of graph concept is not in the right direction so please bear with me
note : bfs algorithm is not an option because that is not what i need. if possible, i would like to get the longest path. my arangodb current version is 3.1.7 running on a cluster with 1 coordinator and 3 db servers
It is worth trying a few queries to get a feel for how AQL traversals work, but maybe start with this example from the AQL Traversal documentation page:
FOR v, e, p IN 1..10 OUTBOUND 'object/45a92a7344ee4f758841b5466c010ed9' GRAPH 'insert_my_graph_name'
LET last_vertex_in_path = LAST(p.vertices)
FILTER last_vertex_in_path.obj_id == '45a92a7344ee4f758841b5466c01111'
RETURN p
This sample query will look at all outbound edges in your graph called insert_my_graph_name starting from the vertex with an _id of object/45a92a7344ee4f758841b5466c010ed9.
The query is then set up to return three variables for every path found:
v contains a collection of vertices for the outbound path found
e contains a collection of edges for the outbound path found
p contains the path that was found
A path is consisted of vertices connected to each other by edges.
If you want to explore the variables, try this version of the query:
FOR v, e, p IN 1..10 OUTBOUND 'object/45a92a7344ee4f758841b5466c010ed9' GRAPH 'insert_my_graph_name'
RETURN {
vertices: v,
edges: e,
paths: p
}
What is nice is that AQL returns this information in JSON format, in arrays and such.
When a path is returned, it is stored as a document with two attributes, edges and vertices, where the edges attribute is an array of edge documents the path went down, and the vertices attribute is an array of vertex documents.
The interesting thing about the vertices array is that the order of array elements is important. The first document in the vertices array is the starting vertex, and the last document is the ending vertex.
So the example query above, because your query is set up as an OUTBOUND query, that means your starting vertex will always be the FIRST element of the array stored at p.vertices' and the end of the path will always be theLAST` element of that array.
It doesn't matter how many vertices are traversed in your path, that rule still works.
If your query was an INBOUND rule, then the logic stays the same, in that case FIRST(p.vertices) will be the starting vertex for the path, and LAST(p.vertices) will be the terminating vertex, which will be the same _id as what you specified in your query.
So back to your use case.. if you want to filter out all OUTBOUND paths from your starting vertex to a specific vertex, then you can add the LET last_vertex_in_path = LAST(p.vertices) declaration to set a reference to the last vertex in the path provided.
Then you can easily provide a FILTER that references this variable, and then filter on any attribute of that terminating vertex. You could filter on the last_vertex_in_path._id or last_vertex_in_path.obj_id or any other parameter of that final vertex document.
Play with it and practice some, but once you see that a graph traversal query only provides you with these three key variables, v, e, and p, and these aren't anything special, they are just arrays of vertices and edges, then you can do some pretty powerful filtering.
You could put filters on properties of any of the vertices, edges, or path positions to do some pretty flexible filtering and aggregation of the results it sends through.
Also have a look at the traversal options, they can be useful.
To get started just make sure your have your documents and edges loaded, and that you've created a graph with those document and edges collections in it.
And yes.. you can have many document and edge collections in a single graph, even sharing document/edge collections over multiple graphs if that suits your use cases.
Have fun!

Tinkerpop3/Gremlin. Find (A) Upsert (B) add Edge A to B

I am looking for an upsert functionality in Gremlin.
Client program has a stream of (personId, favoriteMovieNodeId) that need to query for the favoriteMovieNodeId's, then UPSERT a person Vertex and create the [favoriteMovie] edge.
this will create duplicate Person nodes:
g.V().has(label,'movies').has('uid',$favoriteMovieNodeId).as('fm')
.addV('Person').property('personId', $personId).addE('favMovie').to('fm')
Is there a way to check for existence of node based on properties before adding a node? I can't seem to find the documentation on this very basic graph function thats a part of every underlying graph db.
If the movie is guaranteed to exist, then it's:
g.V().has('movies','uid',$favoriteMovieNodeId).as('fm').
coalesce(V().has('Person','personId', $personId),
addV('Person').property('personId', $personId)).
addE('favMovie').to('fm')

Edge Collection vs. Graph

There's one thing I don't get in ArangoDB:
What's the difference between an edge collection and a graph? In which cases should I choose which?
Graphs in ArangoDB are built on top of documents and edges.
Edge collections have automatic indexes on _from and _to, allowing efficient retrieval of any connected documents. Because data are still stored in regular (document and edge) collections, you can use these collections in non-graph queries, too.
Graphs add some functionality (i.e. query methods, traversals) on top of the data. You can have multiple of them in ArangoDB. Think of a "graph" being a means of grouping for parts or all of your data, and making them accessible in queries.
This is an edge:
{
"_id": "edges/328701573688",
"_from": "nodes/150194180348",
"_to": "nodes/328668871224",
"_rev": "3680146597",
"_key": "328701573688",
"type": "includes"
}
This is a document:
{
"_id": "nodes/328668871224",
"_rev": "3610088613",
"_key": "328668871224",
"name": "Gold-edged Gem",
"type": "species"
}
As you can see there is no fundamental difference. They are both documents. Edge collections are only useful for when you using Arango for it's graph database capabilities.
As I understand it, the point setting the type of the collection to "edge" tells Arango that it should be ensuring that all documents stored in there minimally have _to and _from attributes so that the document can serve its function as a connector between two other documents.
Once you have a document collection whose documents are connected by a bunch of edge documents in an edge collection... now you have a graph.

Resources