Can UNION and WITH play together? - neo4j

Is there any way to use the results of a UNION in another sub-query using a WITH clause?
I'm looking for something like
(
MATCH (me:Person)-[:RATES]->(r:Rating)-[:RATED_BY]->(them:Person)
WHERE me.ident = {id} AND r.date = {date}
RETURN them
UNION ALL
MATCH (me:Person)<-[:RATED_BY]-(r:Rating)<-[:RATES]-(them:Person)
WHERE me.edent = {id} AND r.date = {date}
RETURN them
)
WITH them
RETURN them.name, COUNT( them.name) as ratingCount
ORDER BY ratingCount DESC
LIMIT 10
only nothing like this is supported by cypher.
And yes, I know that in this case I should be using
MATCH (me:Person)-[:RATES|RATED_BY]-(r:Rating)-[:RATES|RATED_BY]-(them:Person)
WHERE me.ident = {id} AND r.date = {date}
RETURN them.name, COUNT( them.name) as ratingCount
ORDER BY ratingCount DESC
LIMIT 10
which is fine and dandy, but I think that I'm going to get some more complex requests down the road where this won't work.

Related

Neo4j match using a list

i have a node like this: (:a{name:'',lname:'',listNumb:[1,3,9]})
i want to select when 1 is in the array
this is what itried to do
match (:a ) where a.listNumb=1 return a ; or match (:a {listNumb=1})
You can use IN to check if a value is present in the array/list.
MATCH (n:a)
WHERE 1 IN n.listNumb
RETURN n;

apoc.periodic.commit doesn't result in updates

The following query results in 10 updated nodes:
MATCH (a:ns3__Organization)-[r:ns4__isDomiciledIn]->(b:Resource)
WITH a,b LIMIT 10
SET a.isDomiciledIn = b.Country
I'm trying to apply it to my whole graph with apoc.periodic.commit through the following query:
CALL apoc.periodic.commit("
MATCH (a:ns3__Organization)-[r:ns4__isDomiciledIn]->(b:Resource)
WITH a,b LIMIT $limit
SET a.isDomiciledIn = b.Country
", { limit : 50000});
Somehow it results in 0 update. What am I doing wrong?
Thanks for your help.
You should try this one :
CALL apoc.periodic.commit("
MATCH (a:ns3__Organization)-[r:ns4__isDomiciledIn]->(b:Resource)
WHERE NOT a.isDomiciledIn = b.Country
WITH a,b LIMIT $limit
SET a.isDomiciledIn = b.Country
RETURN count(*)
", { limit : 50000});
You errors :
no count(*) at the end of your query. SO your query never ends
no WHERE clause to filter the result to only nodes that are not yet updated

Get count of multiple nodes with no relations in cypher query

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

neo4j cypher left padding String in Where Clause

I have a String property in my nodes where the length of the String isn't fix.
Now i must search the right node by this property but i get a fixed length value from another System. For Example my Node has the Value '0123' but I get the Information '000123' for searching.
I need a function like left padding with Zeros and this in the Where Clause like
MATCH (a:LABEL) where leftPad(a.property, 6, '0') = '000123' return a
LIMIT 1
Is something like this possible with a good Performance?
You could do this:
MATCH (a:LABEL)
WHERE SUBSTRING('00000', 0, SIZE(a.property)) + a.property = '000123'
RETURN a
LIMIT 1;
Or, if all the characters are numeric, then you could do this:
MATCH (a:LABEL)
WHERE TOINT(a.property) = TOINT('000123')
RETURN a
LIMIT 1;
However, it would be even better if you could just store the property value as an integer in the first place, and also compare it to an integer, which would be the fastest. This might be very easy to do, depending on your situation.
MATCH (a:LABEL)
WHERE a.property = 000123
RETURN a
LIMIT 1;
Try it with reduce:
MATCH (a:LABEL)
WHERE REDUCE(lp='', n in RANGE(0,5-size(a.name)) | lp+'0')+a. a.property = '000123'
RETURN a
or try it with regular expression:
MATCH (a:LABEL)
WHERE a.property =~ '(0){0,3}123'
RETURN a

Cypher Query, make a where by several nodes properties if they have the same type of relationship

If we have a node related with other nodes by the same type of relationship
classmetadata<-INSTANCE_OF-instance(TheNodeINeed)-RELATED_TO->...................
- ->listype(The owner(name=d,etc))
- ->listype(The state(name=x,etc))
- ->listype(The propertie(name=y,etc))
- ->listype(The location(name=z,etc))
The instance node to find, must be looking by a node classmetadata within a index by its name(this is easy) and instance name (this is easy too) and also by the listype.name=.. and listype.name=.. and listype.name=.. and here is the problem:
If I try looking just for the instance with name MyInstance who is RELATED_TO a owner with name d, here I only quering about one listype node there's no problem, this query works
START classmetadata = node:classes(name = "MyClassMetadata")
MATCH classmetadata<-[:INSTANCE_OF]-instance-[:RELATED_TO]->listype
WHERE instance.name="MyInstance" and listype.name = "d"
RETURN instance, listype
ORDER BY instance.name ASC skip 0 limit 10
but if I need to look for the instance with name MyInstance who is RELATED_TO a owner with name d and is also RELATED to state with name x and is also RELATED to propertie with name y there is a problem the query result is always empty, is there any way to filter about two o three or more nodes.properties(listype.name) at same time if they are related by the same type of relatioship?
something like this is not working
START classmetadata = node:classes(name = "MyClassMetadata")
MATCH classmetadata<-[:INSTANCE_OF]-instance-[:RELATED_TO]->listype
WHERE instance.name = "MyInstance" AND listype.name = "x"
AND listype.name = "y" AND listype.name="d" RETURN instance, listype
ORDER BY instance.name ASC skip 0 limit 10
I added the name property to each relationship in order to be sure that I am making the filtering in the right node.
START classmetadata = node:classes(name = "MyClassMetadata")
MATCH classmetadata<-[:INSTANCE_OF]-instance-[r1:RELATED_TO]->listype1,
instance-[r2:RELATED_TO]->listype2,
instance-[r3:RELATED_TO]->listype3
WHERE instance.name = "MyInstance" AND
r1.name="state" AND listype1.name = "x" AND
r2.name="property" AND listype2.name = "y" AND
r3.name="owner" AND listype3.name="d"
RETURN instance, listype
ORDER BY instance.name ASC skip 0 limit 10
So you want to find all listypes where the name property of listtype can be d or x or y (in your first code snippet)?
If so, then
START classmetadata = node:classes(name = "NodeType ")
MATCH classmetadata<-[:INSTANCE_OF]-instance-[:RELATED_TO]->listype
WHERE instance.state="good" and (not(listype.name in ["d","x","y"]))
RETURN instance, listype
ORDER BY instance.name ASC skip 0 limit 10
Your query above too would work...just refer to listtype uniformly- no need for listtype1, listtype2 etc.
START classmetadata = node:classes(name = "NodeType ")
MATCH classmetadata<-[:INSTANCE_OF]-instance-[:RELATED_TO]->listype
WHERE instance.state="good" and AND listype.name! =~ ".Po."
AND listype.name! =~ ".Me."
RETURN instance, listype
ORDER BY instance.name ASC skip 0 limit 10
Is that what you're looking for?

Resources