Let's say we have a simple graph stored in OrientDB, with an edge type called weightedEdge that has a property weight. I'd like to be able to traverse from a starting node to an arbitrary depth, but only traverse to nodes that have the maximum value of weight on their incoming edge compared to all other edges at the same depth. Is this possible using OrientDB SQL?
So in the given example above, I would only want to hop along the red arrows.
Thank you!
May be you can use a let block and then property selection via [ ]:
traverse out()[weight = $maxW] ...
LET $maxW = SELECT max(weight) FROM ...
Related
I have a couple of questions regarding the capabilities of Dgraph regarding graph traversal.
Let's say we have a dataset that consists of nodes of the type post. Each post can have n posts that are replies to this post. The depth of this tree is not limited.
Is it possible with Dgraph to search trough all leaf nodes starting from one starting node and return all leafs that fulfill a certain condition?
Is it possible to set a depth limit to not end up with a gigantic dataset?
Is it also possible to find the children of all parent nodes that fulfill a certain condition?
And finally: Are edges in Dgraph directed? And can I include that in the query?
Author of Dgraph here.
Is it possible with Dgraph to search trough all leaf nodes starting
from one starting node and return all leafs that fulfill a certain
condition?
Yes. You could use the recurse directive (https://docs.dgraph.io/query-language/#recurse-query).
Is it possible to set a depth limit to not end up with a gigantic
dataset?
Yes. Recursion supports a maximum depth.
Is it also possible to find the children of all parent nodes that fulfill a certain condition?
Yes. You can traverse an edge, and put a filter on it. https://docs.dgraph.io/query-language/#applying-filters
And finally: Are edges in Dgraph directed? And can I include that in the query?
Edges in dgraph are directed. But, Dgraph also supports a "reverse" index, which can be used to automatically generate the edges in the reverse direction. You can then traverse these reverse edges, by adding a tilde (~) in front of the predicate name.
https://docs.dgraph.io/query-language/#reverse-edges
I have a Titan graph database witha set of vertices connected by an edge with a property named "property1".
Is it possible to write a Gremlin (or anything else Titan would support) query to:
Find all edges that have a value for "property1" that is seen 5 or less times.
In SQL I would use "Group By", in MongoDB I would use one of the aggregate functions.
I am thinking this may be a job for Furnace/Faunus?
You can do this by iterating all edges and using groupBy. Here's an example with the toy graph using weight in place of property1:
gremlin> g = TinkerGraphFactory.createTinkerGraph()
==>tinkergraph[vertices:6 edges:6]
gremlin> g.E.groupBy{it.weight}{it}.cap.next()
==>0.5=[e[7][1-knows->2]]
==>1.0=[e[8][1-knows->4], e[10][4-created->5]]
==>0.4=[e[11][4-created->3], e[9][1-created->3]]
==>0.2=[e[12][6-created->3]]
So that groups all edges by their weight. From there you can drop down to standard groovy functions like findAll to filter out what you don't want (here i filter out weights that have >1 edge in them...in your case it would be <5).
gremlin> g.E.groupBy{it.weight}{it}.cap.next().findAll{k,v->v.size()>1}
==>1.0=[e[8][1-knows->4], e[10][4-created->5]]
==>0.4=[e[11][4-created->3], e[9][1-created->3]]
Obviously this is a bit of an expensive operation on a really large graph as you have a lot of iteration to do over edges and you have to build up a Map in memory which could be big depending on the diversity of the values in property1. If you can find ways to limit edge iteration with other filters, that might be helpful.
This would be a good job for Faunus if you had a really large graph. I'll go with the easy answer here and simply say that you don't necessarily want the specific edges with a property1 value occurring less than 5 times and that you just want to know how many times different property1 values occur. With Faunus you could get a distribution like that with:
g.E.property1.groupCount()
I have a large, non-cyclic directed graph.
Every node has some key/value pairs. Some of the keys can be searched by range.
Let's say all nodes have these keys:
color - red, blue, green, etc.
price - an integer
size - an integer
I want to select a list of nodes from my graph such that:
all nodes have color = red
all nodes have price >= 10 and <= 20
the list is ordered by increasing size
any node that meets the criteria for color and price and has no outlinks (no edges go from that node) is in the list
no two nodes in the list share an edge
Ideally, the list would have the maximum number of nodes possibly to satisfy all those constraints.
I need to be able to search this graph very quickly.
What kind of data store (graph or otherwise) is best suited for this problem? Any hints on how to implement schema and query to get the best performance?
Do you have any size estimations on this? That would give some more hints on how you can do the computations - in memory or index or lazy graph loading. /peter neubauer
i'm coding a c project for an algorithm class and i really need some help!
Here's the problem:
I have a set of names like this one N = (James,John,Robert,Mary,Patricia,Linda Barbara) wich are stored in an RB tree.
Starting from this set of names a series of couple like those ones are formed:
(James,Mary)
(James,Patricia)
(John,Linda)
(John,Barbara)
(Robert,Linda)
(Robert,Barbara)
Now i need to merge the elements in a way that i can form n subgroups with the constraint that each pairing is respected and the group has the smallest possible cardinality.
With the couples in the example they will form two groups
(James,Mary,Patricia) and (John,Robert,Barbara,Linda).
The task is to return the maximum number of groups formed and the number of males and females in the group with the maximum cardinality.
In this case it would be 2 2 2
I was thinking about building a graph where every name is represented by a vertex and two vertex are in an edge only if they are paired.
I can then use an algorithm (like Kruskal) to find the Minimum spanning tree.Is that right?
The problem is that the graph would not be completely connected.
I also need to find a way to map the names to the edges of the Graph and vice-versa.
Can the edges be indexed by a string?
Every help is really appreciated :)
Thanks in advice!
You don't need to find the minimum spanning tree. That is really for finding the "best" edges in a graph that will still keep the graph connected. In other words, you don't care how John and Robert are connected, just that they are.
You say that the problem is that the graph would not be completely connected, but I think that is actually the point. If you represent graph edges by using the couples as you suggest, then the vertices that are connected form the groups that you are looking for.
In your example, James is connected to Mary and also James is connected to Patricia. No other person connects to any of those three vertices (if they did, you would have another couple that included them), which is why they form a single group of (James, Mary, Patricia). Similarly all of John, Robert, Barbara, and Linda are connected to each other.
Your task is really to form the graph and find all of the connected subgraphs that are disjoint from each other.
While not a full algorithm, I hope that helps get you started.
I think that you can easily solve this with a dfs and connected components. Because every person(node) has a relation with an other one (edge). So you have an outer loop and run an explore function for every node which is unvisited and add the same number for every node explored by the explore function.
e.g
dfs() {
int group 0;
for(int i=0;i<num_nodes;i++) {
if(nodes[i].visited==false){
explore(nodes[i],group);
group++;
}
}
then you simple have to sort the node by the group and then you are ready. if you want to track the path you can use a pre number which indicates which node was explored first, second..etc
(sorry for my bad english)!
The sets of names and pairs of names already form a graph. A data structure with nodes and pointers to other nodes is just another representation, one that you don't necessarily need. Disjoint sets are easier to implement IMO, and their purpose in life is exactly to keep track of sameness as pairs of things are joined together.
I'm willing to store a Property Graph into HBase. A Property Graph is a graph nodes and edges have properties and multiple edges can link the same tuple of nodes as long as the edges belong to different types.
My query pattern will be either asking for properties and neighborhood or traversing the graph. An example is: Vertex[name=claudio]=>OutgoingEdge[knows]=>Vertex[gender=female], which will give me all the female people that claudio likes.
I know that a graph database does just this, but they usually don't scale on multiple nodes in case of a huge dataset. So I'm willing to implement this on a NoSQL ColumnStore (HBase, Cassandra...)
My datamodel follows.
Vertices Table:
key: vertexid (uuid)
Family "Properties:": <property name>=><property value>, ...
Family "OutgoingEdges:": <edge key>=><other vertexid>, ...
Family "IncomingEdges:": same as outgoing edges...
This table allows me to fetch quickly the properties of a vertex and
its adjacency list. I can't use the vertexid as the other endpoint
because multiple edges (with different types) can connect the same two
vertices.
Edges Table:
key: edge key (composite(<source vertexid>, <destination vertexid>,
<edge typename>)) (i.e. vertexid1_vertexid2_knows)
Family "Properties:": <property name>=><property value>, ...
This table allows me to fetch quickly the properties of an edge.
Edges Types:
key: composite(<source vertexid>, "out|in", <edge typename>) (i.e.
vertexid1_out_knows)
Family "Neighbor:": <destination vertexid>=>null,...
This table allows me to search/scan for edges that are either incoming
or outgoing from a vertex and belong to specific type and would be the
core of the traversing ability of the API (so i want it to be as fast as
possible both in terms of network I/O (RPCs), disk I/O (seek)). It
should also "scale" on the size of the graph, meaning that with the
growth of the graph the cost of this type of operation should depend on
the number of edges outgoing from the vertex and not on the total number
of vertices and edges.
The example above i'd be considering vertexid1 the source vertex with
property name:claudio i'd scan vertexid1_out_knows and receive the list of
vertices connected. After that i can scan on the column
"Properties:gender" on these vertices and look for those having the
"female" value.
Questions:
1) General: do you see a better data model for my operations?
2) Can i fit everything in one table where for certain keys some
families would be empty (i.e. the "OutgoingEdges:" family would not make
sense for the edges)? I'd like that because as you can see all the keys
are composed by the vertexid uuid prefix, so they would be very compact
and fit mostly on the same regionserver.
3) I guess that for the scanning I'd make extensive use of Filters. I
guess regexp Filter will be my friend. Do you have concerns about
performance of filters applied to this data model?
This type of model looks like a sensible starting point for Cassandra (don't know much about HBase) - but for any distributed store you will run up against problems when traversing, because traversals will cross multiple nodes.
This is why dedicated graph databases such as Neo4J use a single-node design, and try to keep all data in RAM.
Looking up properties of particular nodes or edges should work well and scale horizontally - Twitter's FlockDB (now apparently abandoned) was a notable example of this.
You also need to consider whether you need lookups other than by ID (i.e. do you need any indexes)?