So I have the following query:
MATCH (n:Mob)
WITH count(n) as total, collect(n) as nodes
WITH nodes, total
UNWIND nodes as node
WHERE node.order > 8000 AND node.order < 8100
RETURN node, total
What I'm trying to do is to get to the total number of nodes (with label Mob) as a number then filter the actual returning nodes, so that I have a subset of the total nodes.
This currently gives me the error Invalid input 'H': expected 'i/I'. Is there anyway to do what I want in one query, or does it need to be split into two?
You need to have a WITH clause between the UNWIND and MATCH clauses. This should work:
MATCH (n:Mob)
WITH COUNT(n) as total, COLLECT(n) as nodes
UNWIND nodes as node
WITH total, node
WHERE 8000 < node.order < 8100
RETURN total, node
However, this is simpler if you are OK with getting a single list of suitable nodes instead of multiple return records:
MATCH (n:Mob)
RETURN
COUNT(n) AS total,
[m IN COLLECT(n) WHERE 8000 < m.order < 8100] AS nodes, COUNT(n) AS total
[UPDATE]
If you also want to do the equivalent of SKIP and LIMIT (assuming the SKIP and LIMIT counts are passed as parameters skip and limit):
MATCH (n:Mob)
RETURN
COUNT(n) AS total,
[m IN COLLECT(n) WHERE 8000 < m.order < 8100][$skip..($skip+$limit)] AS nodes
Adding to cybersam's answer. In order to SKIP/LIMIT a list you need to do [x..y] where x and y are numbers i.e.
MATCH (n:Mob)
RETURN [m IN COLLECT(n) WHERE 8000 < m.order < 8100][0..10] AS nodes, COUNT(n) AS total
Or
MATCH (n:Mob)
WITH COUNT(n) as total, COLLECT(n) as nodes
UNWIND nodes as node
WITH total, node
WHERE node.order > 1000
WITH total, node
SKIP 10
LIMIT 5
WITH collect(node) as nodes, total
RETURN nodes, total
Related
so in neo4j, I have company nodes and relationships between them as invoices, relationship propertys as invoice amount and products description. I want to sum relationships amount to be left only one arrow, and sumerized amount, i don't want to delete relationships from db. i added this query to the bloom scene action but cant get any result
match(n:company)-[r:invoice]->(m:company)
where id(n) in $nodes
with n, m, sum(r.amount) as total, collect(r) as relationships
where size(relationships) > 1
with total, head(relationships) as keep, tail(relationships) as delete
set keep.w = total
foreach(r in delete | delete r)
return *
You can use use virtual relationships that show the aggregated sums.
match(n:company)-[r:invoice]->(m:company)
where id(n) in $nodes
with n,m, sum(r.amount) as amount, count(*) as rels
where rels > 1
return n,m,apoc.create.vRelationship(n,'TOTAL',{amount:amount},m) as rel
I have the following query
MATCH (n:Mob)
WITH COUNT(n) as total, COLLECT(n) as nodes
UNWIND nodes as node
WITH total, node
WHERE 8000 < node.order < 8100
RETURN node, total
SKIP 10
LIMIT 1
Right now, this query is giving me this error.
If I remove the SKIP part it works.
So my overall question is, how do I SKIP some of the records?
This was mainly a misunderstanding on my part. If you want to filter before bunching them together, then perform the COLLECT at a later stage.
Working code:
MATCH (n:Mob)
WITH COUNT(n) as total, n as node
WITH total, node
WHERE node.order > 1000
WITH total, node
SKIP 10
LIMIT 5
WITH collect(node) as nodes, total
RETURN nodes, total
We have a large graph (over 1 billion edges) that has multiple relationship types between nodes.
In order to check the number of nodes that have a single unique relationship between nodes (i.e. a single relationship between two nodes per type, which otherwise would not be connected) we are running the following query:
MATCH (n)-[:REL_TYPE]-(m)
WHERE size((n)-[]-(m))=1 AND id(n)>id(m)
RETURN COUNT(DISTINCT n) + COUNT(DISTINCT m)
To demonstrate a similar result, the below sample code can run on the movie graph after running
:play movies in an empty graph, resulting with 4 nodes (in this case we are asking for nodes with 3 types of relationships)
MATCH (n)-[]-(m)
WHERE size((n)-[]-(m))=3 AND id(n)>id(m)
RETURN COUNT(DISTINCT n) + COUNT(DISTINCT m)
Is there a better/more efficient way to query the graph?
The following query is more performant, since it only scans each relationship once [whereas size((n)--(m)) will cause relationships to be scanned multiple times]. It also specifies a relationship direction to filter out half of the relationship scans, and to avoid the need for comparing native IDs.
MATCH (n)-->(m)
WITH n, m, COUNT(*) AS cnt
WHERE cnt = 3
RETURN COUNT(DISTINCT n) + COUNT(DISTINCT m)
NOTE: It is not clear what you are using the COUNT(DISTINCT n) + COUNT(DISTINCT m) result for, but be aware that it is possible for some nodes to be counted twice after the addition.
[UPDATE]
If you want to get the actual number of distinct nodes that pass your filter, here is one way to do that:
MATCH (n)-->(m)
WITH n, m, COUNT(*) AS cnt
WHERE cnt = 3
WITH COLLECT(n) + COLLECT(m) AS nodes
UNWIND nodes AS node
RETURN COUNT(DISTINCT node)
I have a subgraph in neo4j with multiple paths, generated via:
match p=((n:Actor)-[*1..3]->(m:film)) where n.surname='Craig' and m.name='Minions' and ALL(x in nodes(p)[1..length(p)-1] where labels(x)[0]='Director') return p
Now, from this subgraph I want a list of tuples, where each tuple is a pair of connected nodes in the subgraph:
node0, node1
node1, node3
node0, node2
node2, node26
I tried:
match p=((n:Actor)-[*1..3]->(m:film))
where n.surname='Craig' and m.name='Minions' and ALL(x in nodes(p)[1..length(p)-1] where labels(x)[0]='Director')
with nodes(p) as np
match p2=((nn)-[]-()) where nn IN np
return p2
but this just returned the nearest neighbour of every single node in p. Including to nodes not in the subgraph.
This seems to work
MATCH p=((n:Actor)-[*1..3]->(m:Film))
WHERE n.surname='Craig' AND m.name='minions' AND ALL(x in nodes(p)[1..length(p)-1] WHERE labels(x)[0]='Director')
MATCH p2=(n2)-[r]-(m2)
WHERE n2 IN nodes(p) AND m2 IN nodes(p)
RETURN
n2,r,m2
However is very slow, any speed up recommendations?
Rather than take all of the data from the paths and rematch it against the graph you could process the paths for pairs in memory. If you take the nodes from each path and process them two an a time, you can collect them in ordered pairs.
...
// for each path grab the nodes
// and an index for them less the last one
//
with nodes(p) as node_list, range(0, size(nodes(p)) - 2, 1) as idx
//
// put the tuples in ordered pairs
//
unwind idx as i
with node_list[i] as a , node_list[i+1] as b
with
case
when id(a) < id(b) then [id(a), id(b)]
else [id(b), id(a)]
end as tuple
return tuple, count(*)
order by count(*) desc
I'm starting with Neo4j and using graphs, and I'm trying to get the following:
I have to find the subtraction(difference) between the number of users (each user is a node) and the number of differents names they have. I have 16 nodes, and each one has his own name (name is one of the properties it has), but some of them have the same name (for example the node A has (Name:Amanda,City:Roma) and node B has (Name:Amanda, City:Paris), so I will have less name's count because some of them are repeated.
I have tried this:
match (n) with n, count(n) as c return sum(c)
That gives me the number of nodes. And then I tried this
match (n) with n, count(n) as nodeC with n, count( distinct n.Name) as
nameC return sum(nodeC) as sumN, sum(nameC) as sumC, sumN-sumC
But it doesn't work (I'm not sure if even i'm getting the names well, because when I try it, separated, it doesn't work neither).
I think this is what you are looking for:
MATCH (n)
RETURN COUNT(n) - COUNT(DISTINCT n.name) AS diff;