Neo4j get edges between 1st degree nodes - graph

Assume i have graph relations defined as A->B, A->D, C->A, B->C, B->D. I need to get the following subgraph in Neo4j -
Get all 1st degree connections (indegree or outdegree) of a node i.e. For node A, it would be B, C, D
Get all the edges between these 1st degree nodes. Since B,C,D are 1st degree connections, edges would be B->C, B->D
For the 1st part, I have the following query -
MATCH (s:Node)->(d:Node)
WHERE s.name = 'A' OR d.name = 'A'
I'm not able to get the 2nd part of the data in the same query. Do i need to iterate through all the nodes?

This is a simple pattern that says that you start the path from the node, then go to the node next to it, then one of which you can return to the starter node:
MATCH (A:Node {name:'A'}) WITH A
MATCH (A)--(FD1:Node)-[r]-(FD2:Node)--(A)
WHERE ID(FD1) > ID(FD2)
RETURN FD1, r, FD2
P.S. And remember that you can not specify the direction of the relationship.

Related

Project disconnected vertex with Gremlin/Tinkerpop

I am looking at a kryo file with the following vertices
# Tree Vertices
V(label=tree, properties={treeId:1, treeName:treeA})
V(label=tree, properties={treeId:2, treeName:treeB})
# Root Node Vertices
V(label=node, properties={treeId:1, nodeId:111, nodeType:root})
V(label=node, properties={treeId:2, nodeId:222, nodeType:root})
There are no edges between the vertices labeled as tree and the vertices labeled as node. There are further edges nodes connected to the root nodes but they are irrelevant to this question. I do not want to add any edges as this graph file gets vended to me and I am treating it as read-only.
Now I want to join/project the treeNames into a traversal over the root nodes.
g.V()
.hasLabel('node').has('nodeType', 'root')
.project('nodeId', 'treeId', 'treeName') # return nodeId, treeId, treeName for each root node
.by(values('nodeId'))
.by(values('treeId'))
.by(""" # pseudo-sqlish gremlin to clarify my intent
select treeName
from V().hasLabel('tree')
.where(values('treeid'), eq($thisNode.values('treeId'))
"""
)
In SQL terms I'd say: I want to run a subquery (fully independent sub traversal starting from scratch) and then join it with my outer traversal on a given property. And again: No edge between trees and roots.
WITH
trees as (SELECT treeId, treeName FROM vertices v WHERE v.label = 'tree'),
roots as (SELECT nodeId, treeId FROM vertices v where v.label = 'node')
SELECT roots.nodeId, roots.treeId, trees.treeName
FROM roots
JOIN trees ON (roots.treeId, trees.treeId)
So I am looking for a way to perform a projection based on another traversal + one of the returned vertex properties
How abusive is this?
How to do it?
You can do it by starting a new traversal inside the project like this:
g.V().hasLabel('node').
has('nodeType', 'root').as('root').
project('nodeId', 'treeId', 'treeName').
by(values('nodeId')).
by(values('treeId')).
by(coalesce(
V().hasLabel('tree').where(eq('root')).
by('treeId').
values('treeName'),
constant('tree not exist')
))
see the example here: https://gremlify.com/bybp7s9mdia
How abusive is this: Very.
starting a sub-query for each node vertex can be very 'heavy' performance-wise.
and it's missing all of the advantages of graph DB if your graph schema doesn't fit your requirement

How to force nodes in rows based on weight of incoming edges

I would like to get a configuration where nodes are placed in rows based on the "weight" of incoming rows. Not sure if "weight" is the right word, but in the following case,
a -> b
b -> c
c -> d
the weight of the incoming edge to d should be 3, because it's 3 edges leading to d from the root. Similarly all nodes that have no incoming edges should be placed at the top. I dont care about the lengths of edges, as long as the rows are correct.
Arbitrarily, I've found that nodes sometimes end up in different rows. E.g., if a node has no incoming edges, it has sometimes ended up in a row after the first.
Is there any way to achieve this?
LOOP over root nodes ( those with no incoming edges )
Do a Breadth First Search ( BFS ) from root
Mark each node visited with distance from root
LOOP over nodes
Add each node to the row where that has its depth == distance from root
If you are looking after the drawing in your own code
LOOP over rows
Draw the node at the end of its row
LOOP over edges
Draw edge between src and destination node
If you are using grahviz, then position the nodes using https://graphviz.org/docs/attrs/pos/

How to generate n edges each between m nodes

I'm having trouble conceptualizing my problem. But essentially if I have m nodes, and want to generate no more than n connections for each node. I also want to ensure that there is a always a path from each node to any other node. I don't care about cycles.
I don't have the proper vocabulary to find this problem already existing though I'm sure it has to exist somewhere.
Does anyone know of a place where this problem is explained, or know the answer themselves?
The simplest way is to construct a Spanning Tree to ensure that all nodes are connected, then add edges that don't violate the maximum number of edges per node until you have the target number of them. In pseudocode:
// nodes[] is a list of all m nodes in our graph
connected_nodes = nodes[0];
// add nodes one by one until all are in the spanning tree
for next_node = 1 to (m-1)
repeat
select node connected_nodes[k] // randomly, nearest, smallest degree, whatever
until degree(k) < n // make sure node to connect to does not violate max degree
add edge between nodes[next_node] and new node connected_nodes[k]
add nodes[next_node] to connected_nodes[]
end for
// the graph is now connected, add the desired number of edges
for e = m+1 to desired_edge_count
select 2 nodes i,j from connected_nodes, each with degree < n
add edge between nodes i and j
end for

Graph Theory - Can a path branch/split/fork?

Given the graph:
With nodes:
A, B, C, D.
and Edges:
A->B, A->C, B->C, B->D, C->D
A path is (under my understanding) a sequence of edges that connect vertices together.
An simple path would be A->B, B->C, C->D.
Is it possible to have a path that has a branch/fork/split?
Example:
A->B, B->C, B->D
No, that's not permitted. The standard definition of a path is a series of one or more nodes v1, v2, ..., vn such that for any two consecutive nodes in the path, there's an edge from the first node to the second. That would rule out the sort of object that you're talking about from being a path.
That's not to say that what you're looking at isn't interesting or couldn't be studied, though. There may be some other definition that captures what you're looking for.

How to get all Graph Nodes in ArangoDB without Start-Node

Like in OrientDB, for get the All Graph Only use 'Select From v'
So far, I have use AQL in ArangoDB with start node:
for v,e,p IN 2 ANY 'user/188802' graph 'a' return p
And now I want to get all graph nodes in ArangoDB without the start node?
Graphs are a grouping of Edge collections. Each Edge collection references _from and _to documents which are stored in Document collections.
The graph traversal queries expect you to have a starting position and it returns the results for that single starting position.
It is possible to identify all possible starting positions, and then run graph traversals over those positions.
You'll need to know the names of the document collections that make up your graph, you can insert them into an AQL query like this:
FOR vertex IN UNION(
(FOR v IN document_collection_1 RETURN v._id),
(FOR v IN document_collection_2 RETURN v._id),
(FOR v IN document_collection_3 RETURN v._id)
)
FOR v, e IN 1..5 OUTBOUND vertex GRAPH 'my_graph_name' OPTIONS { uniqueVertices: true }
RETURN DISTINCT [
{
_from: e._from,
_to: e._to
}
]
Remember that in ArangoDB it is possible for a document collection to be bound to more than one graph, so you'll need to ensure you identify all document collections that are part of the graph.
This query will then extract an array of objects that contain all links defined in the graph. This query focuses only on vertices with edges that are part of the graph. If the vertex has no edge on it, it won't appear in the output as it is not part of the graph.

Resources