Reputation: 361
I have separate cypher queries as follows:
Q1: START m=node(30) MATCH (m)-[d:define]->(n) where d.start=4 RETURN n.name,COUNT(d) as count
Q2: START m=node(30) MATCH (m)-[d:define]->(n) where d.start=5 RETURN n.name,COUNT(d) as count
which return the following sample results:
from Q1:
a | 2
b | 1
c | 4
d | 3
from Q2:
a | 1
b | 1
c | 4
e | 2
I can process the results offline and generate a combined count, but can I combine the two cypher queries above so that I can get the following merged counts from d.start 4 and 5?
a | 2 | 1
b | 1 | 1
c | 4 | 4
d | 3 | 0
e | 0 | 2
What I have so far: how can I continue on the name and the count(d) to the next phase?
START m=node(30)
MATCH (m)-[d:define]->(n)
where d.start=4
WITH m, COLLECT (n.name, COUNT(d)) as from1
MATCH (m)-[d:define]->(n)
where d.start=5
WITH m, COLLECT (n.name, COUNT(d)) as from2
A union doesn't work for me as I don't want to just union the results together. I need to separate the counts coming from d.start=4 and 5 resulting in more like an intersection.
Upvotes: 2
Views: 1733
Reputation: 66957
This query should do what you want:
MATCH (m)-[d:define]->(n)
WHERE ID(m) = 30 AND d.start IN [4, 5]
RETURN n.name AS name, REDUCE(c = [0, 0], x IN COLLECT(d.start) |
CASE WHEN x = 4 THEN [c[0]+1, c[1]] ELSE [c[0], c[1]+1] END) AS counts
ORDER BY name;
You can test it by first creating your sample data:
CREATE (m:Foo), (a:Foo {name: 'a'}), (b:Foo {name: 'b'}), (c:Foo {name: 'c'}), (d:Foo {name: 'd'}), (e:Foo {name: 'e'}),
(m)-[:define {start:4}]->(a),
(m)-[:define {start:4}]->(a),
(m)-[:define {start:4}]->(b),
(m)-[:define {start:4}]->(c),
(m)-[:define {start:4}]->(c),
(m)-[:define {start:4}]->(c),
(m)-[:define {start:4}]->(c),
(m)-[:define {start:4}]->(d),
(m)-[:define {start:4}]->(d),
(m)-[:define {start:4}]->(d),
(m)-[:define {start:5}]->(a),
(m)-[:define {start:5}]->(b),
(m)-[:define {start:5}]->(c),
(m)-[:define {start:5}]->(c),
(m)-[:define {start:5}]->(c),
(m)-[:define {start:5}]->(c),
(m)-[:define {start:5}]->(e),
(m)-[:define {start:5}]->(e);
With the above data (and assuming that the query uses the correct ID
for m
), the query returns:
+---------------+
| name | counts |
+---------------+
| "a" | [2,1] |
| "b" | [1,1] |
| "c" | [4,4] |
| "d" | [3,0] |
| "e" | [0,2] |
+---------------+
Upvotes: 2
Reputation: 5047
I believe you can ditch COLLECT
and only use COUNT
.
Example dataset:
CREATE
(m {name: 1}),
(m)-[:define {start: 4}]->({name: 2}),
(m)-[:define {start: 4}]->({name: 3}),
(m)-[:define {start: 5}]->({name: 4})
Query:
MATCH (m)-[d:define]->()
WHERE d.start=4
WITH m, COUNT(d) as from1
MATCH (m)-[d:define]->()
WHERE d.start=5
RETURN m.name, from1, COUNT(d) as from2
Result:
╒══════╤═════╤═════╕
│m.name│from1│from2│
╞══════╪═════╪═════╡
│1 │2 │1 │
└──────┴─────┴─────┘
Upvotes: 0
Reputation: 2507
MATCH (n)
WHERE ID(n) = 30
MATCH (m)-[d:define]->(n)
where d.start=4
WITH m, COLLECT([n.name, COUNT(c)]) as from1
MATCH (m)-[d:define]->(n)
where d.start=5
WITH m, from1 + COLLECT([n.name, COUNT(c)]) as from2
UNWIND from2 AS row
WITH row[0] AS name, row[1] AS ct
RETURN name, SUM(ct)
Though I'm not totally sure if this will return the counts you expect, because you start by finding n
, but then carry m
forward instead, so that (m)-[d]->(n)
path will match fundamentally different patterns. You're on the right track, though; just keep adding things to a collection until you've got all your result rows, then unwind the one big collection and perform your aggregation or other analysis.
Upvotes: 1