Is there an efficient way with given two nodes to find a set of their common nodes (with defined relationships).
For example, having nodes A1
, B1
, C1
-C4
connected with relationships x
and y
:
A1 --x--> C1
A1 --x--> C2
A1 --x--> C3
B1 --y--> C2
B1 --y--> C3
B1 --y--> C4
a common node set for A1(x)
and B1(y)
would be [C2, C3]
.
This will work in all versions of Neo4j that support the MATCH clause, namely 2.0. 0 and later. This is a minimum length of 3, and a maximum of 5. It describes a graph of either 4 nodes and 3 relationships, 5 nodes and 4 relationships or 6 nodes and 5 relationships, all connected together in a single path.
To create a relationship between two nodes, we first get the two nodes. Once the nodes are loaded, we simply create a relationship between them. The created relationship is returned by the query.
The graphs in the Neo4j Graph Data Science Library support properties for relationships. We provide multiple operations to work with the stored relationship-properties in projected graphs. Relationship properties are either added during the graph projection or when using the mutate mode of our graph algorithms.
Properties are stored as a linked list of property records, each holding a key and value and pointing to the next property. Each node and relationship references its first property record. The Nodes also reference the first relationship in its relationship chain. Each Relationship references its start and end node.
In Gremlin (http://gremlin.tinkerpop.com), this is expressed as such:
setA._().out('x').in('y').retain(setB).back(2)
Here is what each step does:
Tada!
Good luck, Marko.
http://markorodriguez.com
In many cases the structure of the domain can be leveraged to improve performance. Let's say that you know that in general your A
entities have less x
relationships compared to the number of y
relationships on the B
entities. Then you could traverse two steps from the A node and see where the B
node shows up, and filter out the C
nodes this way. Here's some code for this approach:
Set<Node> found = new HashSet<Node>();
for ( Relationship firstRel : a1.getRelationships( Reltypes.x, Direction.OUTGOING ) )
{
Node cNode = firstRel.getEndNode();
for ( Relationship secondRel : cNode.getRelationships( Reltypes.y, Direction.INCOMING ) )
{
Node bNode = secondRel.getStartNode();
if ( bNode.equals( b1 ) )
{
found.add( cNode );
break;
}
}
}
Another way would be to start two threads that scan the relationships from either side.
A third approach would be to create a specialized index that would help answering this kind of queries, which would obviously hurt insert performance.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With