Get count of multiple nodes with no relations in cypher query - neo4j

How to get the count of more than one nodes.
MATCH (n1:node1)
MATCH (n2:node2)
MATCH (n3:node3) where n3.status = "active"
return count(n1) as countOfNode1,
count(n2) as countOfNode2,
count(n3) as countOfNode3
This query is returning duplicated result as
countOfNode1 = 0
countOfNode2 = 0
countOfNode3 = 0
where the real count is
countOfNode1 = 0
countOfNode2 = 3
countOfNode3 = 1
How to do this?
Using 'distinct' also does not solve the problem.
Given as:
return count(distinct n1) as countOfNode1,
count(distinct n2) as countOfNode2,
count(distinct n3) as countOfNode3

One possibility I'm thinking of is this
MATCH (n1:node1) WITH count(n1) as countOfNode1
MATCH (n2:node2) WITH count(n2) as countOfNode2
MATCH (n3:node3) where n3.status = "active" WITH count(n3) as countOfNode3
return countOfNode1,
countOfNode2,
countOfNode3
Or maybe
MATCH (n1:node1), (n2:node2),(n3:node3 {status:"active"} )
return count(n1) as countOfNode1,
count(n2) as countOfNode2,
count(n3) as countOfNode3

Related

How to query with two conditions in Neo4j

I am new with Neo4j and I am stucked trying to get a query with two conditions, where I want to get all the "Autors" related to "Pixar" and "Fox". So far I have tried the following two ways:
MATCH (a:Autor)- [:AUTOR_DE]-> (t:Título) -[:PRODUCIDO_POR] ->( p:Productora {Nombre: "Pixar"}),
and
MATCH (a:Autor)- [:AUTOR_DE]-> (t:Título) -[:PRODUCIDO_POR] ->( p:Productora {Nombre: "Fox"}),
return a,p
and
MATCH (a:Autor)- [:AUTOR_DE]-> (t:Título) -[:PRODUCIDO_POR] ->( p:Productora)
WHERE ( (p:Productora) = "Fox" OR (p:Productora) = "Pixar")
return a,p
Thanks in advance
Assuming that a Productora node stores its name in a name property, and that every Productora node has a unique name, this should work:
MATCH (a:Autor)-[:AUTOR_DE]->(:Título)-[:PRODUCIDO_POR]->(p:Productora)
WHERE p.name = "Fox" OR p.name = "Pixar"
WITH a, COLLECT(DISTINCT p) AS ps
WHERE SIZE(ps) = 2
return a, ps
And this should also work:
MATCH (fox:Productora), (pixar:Productora), (a:Autor)
WHERE fox.name = "Fox" AND pixar.name = "Pixar" AND
(a)-[:AUTOR_DE]->(:Título)-[:PRODUCIDO_POR]->(fox) AND
(a)-[:AUTOR_DE]->(:Título)-[:PRODUCIDO_POR]->(pixar)
return a, fox, pixar

apoc.cypher.mapParallel2 in Neo4j is not giving expected results

I have the following query
MATCH (e) WHERE SIZE((e:Customer)<-[:Transaction]-()) <> 0
AND SIZE(()<-[:Transaction]-(e)) <> 0
MATCH path = (e)-[:Transaction*..10]-(e) return path
I am getting the expected results with the above query.
I am trying to parallelize this query with the following query
MATCH (e:Customer) WHERE SIZE((e)<-[:Transaction]-()) <> 0 AND SIZE(()<-[:Transaction]-(e)) <> 0 WITH
collect(e.ID) AS users CALL apoc.cypher.mapParallel2("match (e:Customer)-[:Transaction*..10]->(e)
where e.ID=_ return e.ID as ll",{},users,10) yield value return value.ll
this query doesn't return anything. Kindly, please help me with this.
Does this query, which is also more efficient, work for you?
MATCH (e:Customer)
WHERE (e)<-[:Transaction]-() AND ()<-[:Transaction]-(e)
WITH collect(e) AS users
CALL apoc.cypher.mapParallel2(
"match (_)-[:Transaction*..10]->(_) return _.ID as ll",
{},users,10) YIELD value
RETURN value.ll

How to check if node globally exists and set condition on it in Cypher?

I'm struggling with problem of creating query in Cypher.
Let's use this graph as an example:
MERGE(a:Person {name:'Alice', age:38, eyes:'brown'})
MERGE(c:Person {name:'Charlie', age:53, eyes:'green'})
MERGE(d:Person {name:'Daniel', age:54, eyes:'brown'})
MERGE(b:Person {name:'Bob', age:25, eyes:'blue'})
MERGE(a)-[:KNOWS]->(c)
MERGE(a)-[:KNOWS]->(b)
MERGE(c)-[:KNOWS]->(d)
MERGE(b)-[:KNOWS]->(d)
I would like to have query that returns me nodes with name = 'Alice' only if there aren't any nodes with name = 'Bob'. So if there is Bob I would like to see no results.
Here is what I've tried:
1) With exists()
MATCH p =(n)-[*1..3]->(b)
WHERE n.name = 'Alice' AND NOT EXISTS ((n {name: 'Bob'})-[*1..3]->(b))
RETURN p
But it returns all nodes and relationships.
2) With none()
MATCH p =(n)-[*1..3]->(b)
WHERE n.name = 'Alice' AND NONE (x IN nodes(p) WHERE x.name = 'Bob')
RETURN p
This returned all nodes, without Bob...
3) with any()
MATCH p =(n)-[*1..3]->(b)
WHERE n.name = 'Alice' AND NOT ANY (x IN nodes(p) WHERE x.name = 'Bob')
RETURN p
But this gave me the same result as above.
I'm running out of ideas how to return Alice only if Bob is not present.
What I would expect from query is to return Alice when I delete Bob, but when such node exists - nothing.
Any help is appreciated:)
Thanks!
You should try this query :
MATCH (n:Person {name:'Alice'})
WHERE NOT (n)-[:KNOWS*..3]-(:Person {name:'Bob'})
RETURN n

How to find all oldest sibling in all families

If I have a lot of families represented like:
(parent:Person)<-[:CHILD_OF]-(child:Person {age:19})
then how would a query look like that finds the oldest child of all families?
I have the following suggestion, but this only returns 1 node:
match (parent:Person)<--(child:Person) return child order by child.age desc limit 1
Probably can be optimized, here's a quick go at it-
match (c:Person)-[:CHILD_OF]->(p)
with p, max(c.age) as maxAge, collect(c) as children
return p,filter (x in children where x.age=maxAge)
match (parent:Person)<--(child:Person) with parent, max(child.age) as maxAge
Match (parent)<--(child:Person) where child.age = maxAge
return *
It might return several childs if they have maximum same age, if you want to return one, you should use one more creteria like
max(id(child))
and you will have
Match (parent:Person)<--(child:Person) with parent, max(child.age) as maxAge
Match (parent)<--(child:Person) where child.age = maxAge with parent, max(id(child)) as maxId
Match (parent)<--(child:Person) where id(child) = maxId return *

NEO4J - Using subquery in CASE

Is it right to use subquery inside CASE ?
MATCH (p:Person)
SET p.total =
CASE
WHEN HAS (p.total)
THEN p.total
ELSE
MATCH (p)-[:CHILD]->(c)
RETURN sum(c.age)
END
RETURN DISTINCT p
I get the following error when I try to do this.
Invalid input ']': expected an identifier character, whitespace, NodeLabel, a property map or a relationship pattern
" MATCH (p)-[:CHILD]->(c)"
You can do it but there will be better ways in the future:
MATCH (p:Person)
SET p.total =
CASE WHEN HAS (p.total)
THEN p.total
ELSE reduce(sum = 0, path in (p)-[:CHILD]->() | sum + (nodes(path)[1]).age)
END
RETURN DISTINCT p
or actually:
MATCH (p:Person)
SET p.total =
COALSECE(p.total,
reduce(sum = 0, path in (p)-[:CHILD]->() | sum + (nodes(path)[1]).age)
)
RETURN DISTINCT p

Resources