Count node depth in neo4j - neo4j

I have this query in Neo4j:
MATCH (sentence:Sentence)-[r*]->(n:Word )
WITH n, COUNT(r) AS c
RETURN n, c
My graph is a linguistic database containing words and dependency relations between them.
This query should return depth of nodes, however the COUNT(r) always returns 1.
When I ommit the COUNT function and write just
WITH n, r AS c
instead (trying in web browser neo4j interface), neo4j returns multiple relations for each word node "n" as expected.
Can you please help me what am I doing wrong, how to count the length of path between sentence node and word node? thanks.

I think it query return n and c and there are multiple record of n so count(r) return 1.
Try this -
MATCH (sentence:Sentence)-[r*]->(n:Word )
WITH n, LENGTH(r) AS depth
RETURN n, depth
You will get depth like this.
Or Try this
MATCH p= (sentence:Sentence)-->(n:Word)
RETURN n, length(p) as depth
http://docs.neo4j.org/chunked/stable/query-functions-scalar.html#functions-length

Finally found the solution myself - it is cypher's LENGTH function:
MATCH (sentence:Sentence)-[r*]->(n:Word )
WITH n, LENGTH(r) AS c
RETURN n, c
found in this useful cheat sheet: http://assets.neo4j.org/download/Neo4j_CheatSheet_v3.pdf

In version 4.x, U should use SIZE function
MATCH (sentence:Sentence)-[r*]->(n:Word )
WITH n, SIZE(r) AS depth
RETURN n, depth
https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-size

Related

how to simplify my cypher with several relationships and the path with several nodes

match p=(a:ACCT_NO)
-[r1:TRX_TO]-(n1:ACCT_NO)
-[r2:TRX_TO]-(n2:ACCT_NO)
-[r3:TRX_TO]-(n3:ACCT_NO)
-[r4:TRX_TO]-(b:ACCT_NO)
-[rb:BELONG_TO]->(c1:CUSTOM_NO{sensitivity:'1'})
-[:RELATE_TO*0..2]-(c2:CUSTOM_NO)
where r1.trxAmt > 10000 and r2.trxAmt > 10000 and r3.trxAmt > 10000 and r4.trxAmt > 10000
and a.acctNo in $doubtAcct
and not n1.acctNo in $fliterAcct
and not n2.acctNo in $fliterAcct
and not n3.acctNo in $fliterAcct
return p;
i want to find the path between a and b, but in the path there are no nodes in the list of $fliterAcct
and trxAmt the attribute of relationships is greater than 10000.
my question is how to simplify my cypher?
because i don't want to find path with n1,n2,n3 and r1,r2,r3 if i need to search in several relationships.
whether i can use the pattern like [r:TRX_TO*...3] (actually i try,but the error is Type mismatch: expected Any,
Map, Node or Relationship but was List (line 2, column 7 (offset: 54)) "where r.trxAmt > 10000")
Here is a simplified query:
MATCH p = (a:ACCT_NO)-[rels:TRX_TO*4]-(:ACCT_NO)-[:BELONG_TO]->(:CUSTOM_NO{sensitivity:'1'})-[:RELATE_TO*0..2]-(:CUSTOM_NO)
WHERE a.acctNo in $doubtAcct AND
ALL(r IN rels WHERE r.trxAmt > 10000) AND
NONE(n IN NODES(p)[1..3] WHERE n.acctNo in $fliterAcct)
RETURN p;
[EDITED]
Or, since the usage of identifiers for variable-length relationships has been deprecated since version 3.2, you can do this instead:
MATCH p = (a:ACCT_NO)-[:TRX_TO*4]-(:ACCT_NO)-[:BELONG_TO]->(:CUSTOM_NO{sensitivity:'1'})-[:RELATE_TO*0..2]-(:CUSTOM_NO)
WHERE a.acctNo in $doubtAcct AND
ALL(r IN RELATIONSHIPS(p)[0..3] WHERE r.trxAmt > 10000) AND
NONE(n IN NODES(p)[1..3] WHERE n.acctNo in $fliterAcct)
RETURN p;
You're on the right track, a variable-length pattern is the right way to go, but you'll need to use a different approach to ensure that all nodes and relationships adhere to the restrictions you want.
match p=(a:ACCT_NO)-[:TRX_TO*4]-(b:ACCT_NO)-[rb:BELONG_TO]->(c1:CUSTOM_NO{sensitivity:'1'})-[:RELATE_TO*0..2]-(c2:CUSTOM_NO)
where a.acctNo in $doubtAcct and all(rel in relationships(p) where type(rel) <> 'TRX_TO' OR r.trxAmt > 10000)
and none(node in nodes(p) where node in $fliterAcct)
return p;

How do I write this Neo4j Query?

There are three node types: A, B and C.
I need all the A's and B's and only the C's that participate in exactly one relationship.
match (n)
where n:A or n:B or (n:C)-[]-()
with count(n) as countOfRels
where countOfRels > 0
return n
Not close, I know. I'm not sure where to go from here.
It's a bit strange that A, B and C do not seem to be related ... but here's how you could solve your question for C :
MATCH (n:C)
WHERE size((n)-[]-()) = 1
RETURN n
UNION
MATCH (n:A)
RETURN n
UNION
MATCH (n:B)
RETURN n;
Hope this helps.
Regards,
Tom
you can use this
match(n)
where n:A OR n:B OR (n:C)-[r]-()
with count(r) as countOfRels
where countOfRels > 0
return n
Hope this helps.
You can do MATCH (a)--() WHERE NOT ()--(a)--() to match "nodes with only one relation". After that, You can use UNION or COLLECT()+UNWIND to combine the separate queries into one row result set.
// using Union
MATCH (n:C)--()
WHERE NOT ()--(n)--()
RETURN n
UNION
MATCH (n:A)
RETURN n
UNION
MATCH (n:B)
RETURN n;
// Using collect
OPTIONAL MATCH (a:A)
OPTIONAL MATCH (b:B)
OPTIONAL MATCH (c:C)--() WHERE NOT ()--(c)--()
WITH COLLECT(a)+COLLECT(b)+COLLECT(c) as nodez
UNWIND nodez as n
RETURN DISTINCT n

How do I find pairs of nodes that are not connected in n hops?

As the title says, I have a graph of nodes which are interconnected with a relationship N. I now want to find all pairs of nodes which are further than 20 hops away from each other.
A naive approach with the following cypher query is far too slow:
MATCH (n:CELL)
WITH n
MATCH (k:CELL)
WHERE NOT (n)-[:N*1..20]->(k)
RETURN n, k
I could create a second relationship K with a "distance" property and then match that, but to do so for every Node doesn't exactly scale well (I've got 18k nodes, so I would need more than 160 million new relationships).
Is there any other way to solve this in neo4j?
You could try to use shortest-path which is more efficient.
MATCH (n:CELL)
WHERE shortestPath((n)-[:N*..20]->(k:CELL)) IS NULL
RETURN n, k
What about something like this:
MATCH p=((n:CELL-[:N*..20]->(k:CELL))
WITH n, k, min(length(p)) as minDinstance
WHERE minDinstance > 20/2 AND n <> k
RETURN DISTINCT n, k, minDinstance

Cypher: Graph a nodes's connections 3 deep

given a node, I want to use D3 to graph it, and it's neighborhood 3 deep.
The best strategy I can come up with is:
Query1: MATCH (n)-[r]-(m) WHERE id(n) IN [501] RETURN n, r, m
Then from the results, in my app, collect all of m's id's, put those new id's in the IN clause (remove the ones I've already done), and repeat the query.
Query2: MATCH (n)-[r]-(m) WHERE id(n) IN [502,511,1111] RETURN n, r, m
Query3: MATCH (n)-[r]-(m) WHERE id(n) IN [512,519,1116,1130] RETURN n, r, m
Note: we don't know the id's of the 2nd query till after the 1st, etc.
But this means running 3 query's, and lost of IO shuffling.
Is there a better better way to do this? I feel like I'm doing too much work in my app, when it should be done in cypher. I looked in the D3 examples, but didn't see this kind of query.
Thanks!
Mike
You can run following query or similar, but the concept should be easy to understand:
MATCH (n)-[r*1..3]-(m) WHERE id(n) IN [501] RETURN n, r, m
Where *1..3 means match from 1 to 3 relationships away from the n node
This way it is only a single query and should be significantly faster then running three separate queries
Does this work?
MATCH (n)-[r]-(m)-[s]-(o) WHERE id(n) IN [501] RETURN n, r, m, s, o
Does this work for you?
MATCH (n)-[r1]-(m1)-[r2]-(m2)-[r3]-(m3)
WHERE ID(n) = 501 AND
ID(m2) IN [502,511,1111] AND
ID(m3) IN [512,519,1116,1130]
RETURN n, r1, m1, r2, m2, r3, m3;
Why not just combine all 3:
MATCH (n)-[r]-(m)
WHERE id(n) IN [501]
WITH m
MATCH (m)-[s]-(o)
WITH o
MATCH (o)-[t]-(p)
RETURN o,t,p
The difference between this and the other answers is that this will revisit relationships especially because there is no direction specified, if that's what you want.
How about this: with "resultDataContents":["graph"]
MATCH path = (n)-[*..3]-(m)
WHERE id(n) IN [501]
RETURN path
or if you want to save bandwidth
MATCH path = (n)-[*..3]-(m)
WHERE id(n) IN [501]
RETURN [x in nodes(path) | id(x)] as node_ids, [x in rels(path) | id(x)] as rel_ids
Thanks for the answers, they didn't work out for me.
I did this:
Set idsTodo to the initial node.
Then ran this:
MATCH (n)-[r]->(m) WHERE id(n) IN {idsTodo} RETURN n, r, m
Added idsTodo to idsDone
Then added m.ids to a idsTodo, then subtracted idsDone
Then ran the query again, repeating 2 more times.
By the end, I had every node and it's relationships.

cypher subquery: get node with max/min value and process it

I struggle to return the node with the largest value, and process that node further.
Here's how I would return a node with the largest value:
START n=node(startnode)
MATCH n-[:TYPE]-m
RETURN m
ORDER BY m.value DESC LIMIT 1
but now I am in a subquery
START n=node(somenode)
MATCH n-[:TYPE1]-q
WITH DISTINCT q
MATCH q-[:TYPE2]-m
and then the ORDER BY .. LIMIT 1 obviously doesn't work anymore because I want one result for each q.
How is this done?
Also, once I have the m with largest value for each q I'll also need to process it:
RETURN q, m.maxvalue, x.anothervalue
from
MATCH m-[:HAS_ONE_LINK_TO]->x
So while I've been playing with collections (collect(m) ), I haven't figured a way to expand them back to "result rows" for applying that MATCH.
Untested... let me know if it works for you:
START n=node(somenode)
MATCH n-[:TYPE1]-q // initial query
WITH DISTINCT q
MATCH q-[:TYPE2]-m
WITH q, max(m.value) as max // get max for q
MATCH q-[:TYPE2]-m
WHERE m.value = max // find the max m for each q
WITH q, m
MATCH m-[:HAS_ONE_LINK_TO]->x // find x from m
RETURN q, m, x
Edit: because of recent upvotes on this old answer... please consider a fresher query written in 3.x era using collect/unwind -- also untested (take care to not do this if the number of ms will be quite large, as they may be stored in the partial result of the query instead of being able to stream them):
MATCH (n:Label)-[:TYPE1]-(q) // initial query
WITH DISTINCT q
MATCH (q)-[:TYPE2]-(m)
WITH q, max(m.value) as max, collect(m) as ms // get max for q, collect ms
UNWIND ms as m
WHERE m.value = max
MATCH (m)-[:HAS_ONE_LINK_TO]->(x) // find x from m
RETURN q, m, x

Resources