combine several apoc.path.expand calls into one - neo4j

I have a several cypher calls that returns the count of the nodes from a specific type (A, B or C) that are connect to my node
MATCH (n {{ID:"{id}"}})
call apoc.path.expand(n, "<", ">A", 1, 10) yield path as p
return count(distinct nodes(p)[-1])
MATCH (n {{ID:"{id}"}})
call apoc.path.expand(n, "<", ">B", 1, 10) yield path as p
return count(distinct nodes(p)[-1])
MATCH (n {{ID:"{id}"}})
call apoc.path.expand(n, "<", ">C", 1, 10) yield path as p
return count(distinct nodes(p)[-1])
Making these calls 3 time is wasteful, and I wonder if I can combine them into one, but still get the distinct count for all three

Does something like this get it done for you?
MATCH (n {{ID:"{id}"}})
CALL apoc.path.expand(n, "<", ">A,>B,>C", 1, 10) yield path as p
RETURN labels(last(nodes(p)))[0] AS label, count(distinct nodes(p)[-1])

Related

Neo4j Single Query to Refactor Relationships To and From

I have 2 nodes where I want to move all the TO and FROM relationships to the second node.
//This works FROM
MATCH (c)<-[r:HAS]-(f {name: 'ball(a)'}), (t {name: 'ball(b)'})
WITH c, r, f, t
CALL apoc.refactor.from(r, t)
YIELD input, output
Return c
//AND this works TO
MATCH (c)-[r:HAS]->(f {name: 'ball(a)'}), (t {name: 'ball(b)'})
WITH c, r, f, t
CALL apoc.refactor.to(r, t)
YIELD input, output
Return c
//THIS DOES NOT WORK
MATCH (c)-[r:HAS]->(f {name: 'ball(a)'})-[r2:HAS]->(d), (t {name: 'ball(b)'})
WITH c, r, f, t, r2, d
CALL apoc.refactor.to(r, t)
CALL apoc.refactor.from(r2, t)
YIELD input, output
Return c
I get the ERROR: "Procedure call inside a query does not support naming results implicitly"
How can I refactor TO and FROM relations in one query?
Please try this:
MATCH (c)-[r:HAS]->(f {name: 'ball(a)'})-[r2:HAS]->(d), (t {name: 'ball(b)'})
WITH c, r, t, r2, d
CALL apoc.refactor.to(r, t)
YIELD input, output
WITH c, r2, t
CALL apoc.refactor.from(r2, t)
YIELD input, output
Return c
Line number 3 is a function that takes an input r, t and as a result returns input, output. Inside this return you do not have r2 and t, that's why you're receiving an error.

Cypher variable lenght pattern aggregated property filtering

I'm working on neo4j and I'm trying to put a condition on a series of relationships, where I need to sum a property of said relationship.
When I do the basic textbook part of filtering for the relationship without the sum, it all works.
MATCH c= (a)-[:VENDE*2..3]->(b)
WHERE ALL (r IN relationships(c)
WHERE r.ammontare = 25000)
RETURN c
When I try to put the condition on the sum of said property, I can't find a way.
I tried REDUCE but it's stuck because the this error I didn't manage to work around: "Type mismatch: accumulator is Integer but expression has type Boolean"
MATCH c= (a)-[:VENDE*2..3]->(b)
WHERE ALL (r IN relationships(c)
WHERE REDUCE( t = 0, n in relationships(c)|t= t+ n.ammontare) = 25000)
RETURN c
I tried with apoc but this doesn't work either. What am I getting wrong?
MATCH c= (a)-[:VENDE*2..3]->(b)
WHERE all(r in relationships(r)
WHERE APOC.COLL.SUM( [r IN relationships(c)| r.ammontare]) = 25000)
return c
The last method runs but it's too heavy and goes into timeout.
MATCH c= (a)-[:VENDE*2]->(b)
WITH c, relationships(c) as rels
UNWIND (rels) as rel
With c, sum(rel.ammontare) as re
where re > 25000
return c
I'm not sure but this will work.
MATCH c= (a)-[:VENDE*2..3]->(b)
WHERE ALL (r IN relationships(c)
WHERE REDUCE( t = 0, n in relationships(c)| t+ n.ammontare) = 25000)
RETURN c

Is there a way i can return all the nodes their relationship and it's properties for the following query

I want to get all the list of distinct nodes and relationship that I am getting through this query.
MATCH (a:Protein{name:'9606.ENSP00000005995'})-[r:ON_INTERACTION_WITH]-(b:Protein)-[d:ON_INTERACTION_WITH]-(c:Protein)
Return a,b,c,d,r
limit 10
This should work:
MATCH (a:Protein{name:'9606.ENSP00000005995'})-[r:ON_INTERACTION_WITH]-(b:Protein)-[d:ON_INTERACTION_WITH]-(c:Protein)
WITH * LIMIT 10
RETURN
COLLECT(DISTINCT a) AS aList,
COLLECT(DISTINCT b) AS bList,
COLLECT(DISTINCT c) AS cList,
COLLECT(DISTINCT r) AS rList,
COLLECT(DISTINCT d) AS dList

Invalid use of aggregating function max

match(n)-[r:LIKES]->(m) with count(n) as cnt, m where cnt = max(cnt) return m
Above query results in following error:
Invalid use of aggregating function max(...) in this context (line 1,
column 61 (offset: 60))
This query should return a collection of the m nodes that have the maximum count. It only needs to perform a single MATCH operation, and should be relatively performant.
MATCH (n)-[:LIKES]->(m)
WITH m, COUNT(n) AS cnt
WITH COLLECT({m: m, cnt: cnt}) AS data, MAX(cnt) AS maxcnt
RETURN REDUCE(ms = [], d IN data | CASE WHEN d.cnt = maxcnt THEN ms + d.m ELSE ms END) AS ms;
If you're just trying to find a single node that has the most LIKES relationships leading to it, then you can add an ORDER BY and LIMIT:
MATCH (n)-[:LIKES]->(m)
WITH m, count(n) AS cnt
ORDER BY cnt DESC
LIMIT 1
RETURN m
However, that query has the limitation in that if more than one node has the maximum number of inbound relationships, then those tied nodes won't be returned. To achieve that result, you might try something like this:
MATCH (n)-[:LIKES]->(m)
WITH m, count(n) AS cnt
WITH MAX(cnt) AS maxcnt
MATCH (o)
WHERE size((o)<-[:LIKES]-()) = maxcnt
RETURN o

Neo4j - Return a path only when relationship property between all of the pairs of nodes exists

Let's say, I have a path A->B->C->D and the relationships have a property val.
Now, I have to pick any two nodes from the path and if the rel.val>0.8
and if it is true for all the pair of nodes, then return the path
Ex:
P = A-->B-->C-->D
All nodes = [A,B,C,D]
return p if{
rel.val of (A,B) >0.8
rel.val of (A,C) >0.8
rel.val of (A,D) >0.8
rel.val of (B,C) >0.8
rel.val of (B,D) >0.8
rel.val of (C,D) >0.8
}
Here is my query, (of course the query is wrong):
MATCH p=(a{word:"quality"})-[r*1..2]->(b)
WHERE NONE (n IN nodes(p) WHERE size(filter(x IN nodes(p) WHERE n = x))> 1)
MATCH q = (a)-[r:coocr]->(b) where a in nodes(p) AND b in nodes(p) AND NOT b = a AND None(rel IN rels(q) WHERE rel.val < 0.8 )
RETURN p
In summary, you want to MATCH a path and then make sure that all pairs of nodes in your path are connected by a relationship which fullfills a certain criterion (rel.val > 0.8).
Interesting question, I think this is not really straightforward. Maybe I am overlooking something obvious?
Here is an idea how to approach the problem. You first MATCH your path, then MATCH between all nodes in the path and count the number of relationships with rel.val > 0.8. This number has to be the size of the factorial of the number of nodes (num relationships == (num nodes)!, number of possible combinations of 2).
The following query returns the number of relationships, but I don't know how to compare this to the factorial of the number of nodes:
// match your path like before
MATCH p=(a:Uselabel {word:"quality"})-[r:USETYPE*1..2]->(b)
// use unwind to get the nodes from the path
UNWIND nodes(path) AS x
// do this twice to match the nodes onto themselves
UNWIND nodes(path) AS y
// match your relationship
MATCH (x)-[rel:USETYPE]-(y)
// criterion for your relationship
WHERE rel.val > 0.8
// only if two different nodes
WHERE x <> y
// get the count of pairs
WITH p, count(DISTINCT rel) AS num_pairs
// now I don't know how to get/compare the factorial of the number of nodes :)
RETURN num_pairs
I didn't find a built-in function for the factorial, so you have to look into this.

Resources