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'))
Related
For example, there are two types of vertex in Graph [ Account , User]. Account vertexes have edges to user vertex denoting a list of users form an Account vertex.
User vertex has two property ( name, phoneNumber). I want to select accounts who are connected to more than 2 users whose name starts with foo.
The output should not contain accounts who have more than 2 edges to User vertex but out of all those users, only 1 user's name starts with foo. At minima, 2 users should have name which starts with foo.
This query would do it:
g.V().hasLabel("Account")
.where(out().hasLabel("User")
.has("name", startingWith("foo"))
.count().is(gte(2)))
Given a start node (_id) I need to get all nodes and edges connected to this starting node (within a named graph) and then create a new database with this "subgraph". I wonder if there is a built-in, or fast, way to do this, I was searching in arangoexport but cannot find how to specify graph name and node _id to create the subset of the graph to export.
Thanks
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.
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!
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')