How to find out connection between a set of nodes? - neo4j

I have a scenario where I know IDs of a list of nodes.
I need to get connection(if exists) between these nodes given their IDs.
Is there any way to achieve this?
Update:
I am using node id property not the neo4j's internal ID(using like match (n:Person{id:3}))

You can use the IN clause to select from a list of values:
MATCH (n)-[r*..2]-(m)
WHERE ID(n) IN [0,1,2] AND ID(m) IN [2,3,4]
RETURN r
I've limited the path length to 2 hops of indeterminate relationship type here, and arbitrarily picked some IDs.
To return the path instead:
MATCH p=(n)-[r*..2]-(m)
WHERE ID(n) IN [0,1,2] AND ID(m) IN [2,3,4]
RETURN p

START n=node(1,2,3,4,5,6) //your IDs of a list of nodes
MATCH p=n-[r]-m //the connection for 1 hop. for multiple hops do n-[r*]-m
WHERE Id(m) in [1,2,3,4,5,6] //your IDs of a list of nodes
RETURN p

Related

How Many Nodes Are Involved in a Match

How can I know how many nodes and edges are involved in a MATCH? Is there another way besides Explain / Profile Match?
If you mean how many nodes are matched in a path, such as a variable-length path, then you can assign a path variable for this:
MATCH p = (k:Person {name:'Keanu Reeves'})-[*..8]-(t:Person {name:'Tom Hanks'})
WITH p LIMIT 1
RETURN p, length(p) as pathLength, length(p) + 1 as numberOfNodesInPath
You can also use nodes(p) and relationships(p) to get the collection of nodes and relationships that make up the path, and you can use size() on those collections to get their size.
There exists the COUNT() function of Cypher that allows you to count the number of elements. As for example in this query:
MATCH (n)
RETURN COUNT(n);
This query will count all nodes in your database.
You can find more information in the cypher manual, under the aggregating functions. Check it out.
The following Cypher snippet should return the number of distinct nodes and relationships found by any given MATCH clause. Just replace <your code here> with your MATCH pattern.
MATCH <your code here>
WITH COLLECT(NODES(p)) AS ns, SUM(SIZE(RELATIONSHIPS(p))) AS relCount
UNWIND ns AS nodeList
UNWIND nodeList AS node
RETURN COUNT(DISTINCT node) AS nodeCount, relCount;

cypher NOT IN query with Optional Match

NOT RELEVANT - SKIP TO Important Edit.
I have the following query:
MATCH (n)
WHERE (n:person) AND n.id in ['af97ab48544b'] // id is our system identifier
OPTIONAL MATCH (n)-[r:friend|connected|owner]-(m)
WHERE (m:person OR m:dog OR m:cat)
RETURN n,r,m
This query returns all the persons, dogs and cats that have a relationship with a specific person. I would like to turn it over to receive all the nodes & relationships that NOT includes in this query results.
If it was SQL it would be
select * from graph where id NOT IN (my_query)
I think that the OPTIONAL MATCH is the problematic part. I How can I do it?
Any advice?
Thanks.
-- Important Edit --
Hey guys, sorry for changing my question but my requirements has been changed. I need to get the entire graph (all nodes and relationships) connected and disconnected except specific nodes by ids. The following query is working but only for single id, in case of more ids it isn't working.
MATCH (n) WHERE (n:person)
OPTIONAL MATCH (n)-[r:friend|connected|owner]-(m) WHERE (m:person OR m:dog OR m:cat)
WITH n,r,m
MATCH (excludeNode) WHERE excludeNode.id IN ['af97ab48544b']
WITH n,r,m,excludeNode WHERE NOT n.id = excludeNode.id AND (NOT m.id = excludeNode.id OR m is null)
RETURN n,m,r
Alternatively I tried simpler query:
MATCH (n) WHERE (n:person) AND NOT n.id IN ['af97ab48544b'] return n
But this one does not returns the relationships (remember I need disconnected nodes also).
How can I get the entire graph exclude specific nodes? That includes nodes and relationships, connected nodes and disconnected as well.
try this:
match (n) where not n.id = 'id to remove' optional match (n)-[r]-(m)
where not n.id in ['id to remove'] and not m.id in ['id to remove']
return n,r,m
You've gotta switch the 'perspective' of your query... start by looping over every node, then prune the ones that connect to your person.
MATCH (bad:person) WHERE bad.id IN ['af97ab48544b']
WITH COLLECT(bad) AS bads
MATCH path = (n:person) - [r:friend|:connected|:owner] -> (m)
WHERE n._id = '' AND (m:person OR m:cat OR m:dog) AND NOT ANY(bad IN bads WHERE bad IN NODES(path))
RETURN path
That said, this is a problem much more suited to SQL than to a graph. Any time you have to loop over every node with a label, you're in relational territory, the graph will be less efficient.

neo4j how to use count(distinct()) over the nodes of path

I search the longest path of my graph and I want to count the number of distinct nodes of this longest path.
I want to use count(distinct())
I tried two queries.
First is
match p=(primero)-[:ResponseTo*]-(segundo)
with max(length(p)) as lengthPath
match p1=(primero)-[:ResponseTo*]-(segundo)
where length(p1) = lengthPath
return nodes(p1)
The query result is a graph with the path nodes.
But if I tried the query
match p=(primero)-[:ResponseTo*]-(segundo)
with max(length(p)) as lengthPath
match p1=(primero)-[:ResponseTo*]-(segundo)
where length(p1) = lengthPath
return count(distinct(primero))
The result is
count(distinct(primero))
2
How can I use count(distinct()) over the node primero.
Node Primero has a field called id.
You should bind at least one of those nodes, add a direction and also consider a path-limit otherwise this is an extremely expensive query.
match p=(primero)-[:ResponseTo*..30]-(segundo)
with p order by length(p) desc limit 1
unwind nodes(p) as n
return distinct n;

looking for a clean way to find relationships from a set of nodes

I have got a set of nodes and I would like to write a query to find every relationships which exist between these nodes.
Any recommendation?
My first attemp would be a MATCH a-[rel]-b WHERE... and my WHERE clause would be a OR of all the ids I have in my set of nodes.
Any better idea?
In these answers, I assume you will pass the ID list as a parameter named ids.
If you want to exclude relationships from a node to itself:
MATCH (a)-[r]-(b)
WHERE id(a) IN {ids} AND id(b) IN {ids} AND a <> b
RETURN r;
If you want to include relationships from a node to itself:
MATCH (a)-[r]-(b)
WHERE id(a) IN {ids} AND id(b) IN {ids}
RETURN r;
You could do something like this:
MATCH (a)-[rel]-()
WHERE ID(a) IN {node_ids}
RETURN rel, ID(rel), type(rel), ID(startNode(rel)), ID(endNode(rel))
Here you'd be passing in a node_ids parameter which would be an array.
Note also that using internal Neo4j IDs for long-term reference to nodes may break if Neo4j defragments the nodes.

How to get a list of node properties with Cypher in Neo4j?

I'm trying to list all of the properties for a set of nodes.
Match (n:"Indicator")
return properties(n), ID(n)
I'm unsure of the syntax and couldn't find the answer in the refcard or docs.
In Neo4j version 3.0.0 you may do:
Match (n:Indicator) return properties(n), ID(n)
To return the ID and properties of nodes.
At the moment you can't do this using cypher but it is on the top five on the ideas board.
MATCH (n)
RETURN DISTINCT keys(n), size(keys(n))
ORDER BY size(keys(n)) DESC
Properties(n) works if you need the properties of the node with the key and value, but if you only need to see the properties name's in a easy way you can do this.
Example:
MATCH (n:Indicator) return ID(n), keys(n), size(keys(n))
Results:
Results from Neo4j browser
You can quit ID(n) and size(keys(n)) without problem but is good if you need to identify a node that dont have the required properties or is not complete.
Also you can use a DISTINCT if you have generic and repetitive properties on the same type of Node like this.
MATCH (n:Indicator) return DISTINCT ID(n), keys(n), size(keys(n))
As I have said this also works without problems and give you the array of properties that you need.
MATCH (n:Indicator) return keys(n)
Result only returning keys
But you can resume this long list of results, with a DISTINCT
MATCH (n:Indicator) return DISTINCT keys(n)
Result with only the differents lists of properties that the Node (n) have
If you have APOC installed, I use this to get a distinct list of all node property combinations:
MATCH (n)
RETURN DISTINCT apoc.coll.sort(keys(n)) as props
,size(keys(n)) as key_size
Note: you don't have to use APOC, but if you don't you'll get duplicates where values are same, but ordering is different, so sorting combines them
in the case where the keys are returned in different orders, this does the trick:
MATCH (n)
UNWIND keys(n) AS allProps
RETURN COLLECT(DISTINCT allProps) as distinctProps
MATCH (n:Label)
WITH DISTINCT(keys(n)) as key_sets
UNWIND(key_sets) as keys
RETURN DISTINCT(keys) as key
This will return a clean list of distinct keys

Resources