A cypher query in neo4j can be written with WHERE clause:
match (n:PERSON) where n.name = 'Jonash' return n
But it can be also written with parentheses:
match (n:PERSON {name: 'Jonash'}) return n
Is this always possible for different operators, like contains, > or <?
Since 4.4 you can do node pattern predicates like this:
match (m:Movie where m.title contains "Matrix" and m.released = 1999)
return m
From cypher manual: https://neo4j.com/docs/cypher-manual/current/clauses/where/#node-pattern-predicates
But the short hand (n:Label{propertyKeyName: propertyKeyValue}) syntax is only there for equality.
Related
I am using neo4j to store data with nodes having 1 of 2 labels :Person and Organization. All nodes have a property :name
All the relationships are labeled LinkedTo and have a property :score. There might be multiple relations between one pair of Person and Organization nodes
I have used path queries to search paths between these nodes like:
MATCH (n:Person) WHERE n.name =~ "(?i)person1"
MATCH (m:Organization) WHERE m.name =~ "(?i)organization1"
WITH m,n
MATCH p = (m)-[*1..4]-(n)
RETURN p ORDER BY length(p) LIMIT 10
This returns all paths (upto 10)
Now I want to find specific paths, with all relations involved having a score=1. Not sure how to achieve this, I started with MATCH p = (m)-[f*1..4]-(n) but it got a deprecation warning. So after some googling and trials and errors, I came up with this:
MATCH (n:Person) WHERE n.name =~ "(?i)person1"
MATCH (m:Organization) WHERE m.name =~ "(?i)organization1"
WITH m,n
MATCH p = (m)-[*1..4]-(n)
WITH filter(x IN relationships(p) WHERE x.score=1) AS f
ORDER BY length(p)
UNWIND f AS ff
MATCH (a)-[ff]-(b)
RETURN a,b,ff LIMIT 10
But this is not correct and not clean and is giving me relationships and nodes that are not needed in the path.
This might be a basic cypher query but I am just a beginner and need help with this. :)
From what I have understand you are searching this query :
MATCH p = (m:Organization)-[rels*1..4]-(n:Person)
WHERE
n.name =~ "(?i)person1" AND
m.name =~ "(?i)organization1" AND
all(r IN rels WHERE r.score=1)
RETURN p
ORDER BY length(p)
Due to all(r IN rels WHERE r.score=1), Neo4j will just expand relationships in the path that have an attribute score set to 1.
Also you should note that you are using a regex condition for the node n & m, and this operator can't use indexes !
If your goal is to have a case-insensitive search, I advise you to create a sanitize field (ex _name) to store the name in lower-case, and to replace your regex with a CONTAINS or STARTS WITH
Beginner Cypher query. I know how to use a regex in a MATCH expression:
MATCH (p:Person)
WHERE p.name =~ '(?i).*Rebecca.*'
RETURN p;
And I also know the more compact form for MATCH expressions without regexes:
MATCH (p:Person {name:"Rebecca"})
RETURN p;
But is there any way I can use the regex in the more compact form?
No you can't. Inline queries are only aware of an EQUALS operator.
So
MATCH (n:Person {name:"Rebecca"})
is always translated to name EQUALS Rebecca
Code from LIKE clause in CYPHER Query
MATCH (n) WHERE n.name =~ '(?i).*SUBSTRING.*' RETURN n;
results in
Expected 1 to be a java.lang.String, but it was a java.lang.Long (cause of =~)
Is there a way to for strings case insensitive in all possible places?
If
MATCH (n) WHERE str(n.name) =~ '(?i).*SUBSTRING.*' RETURN n;
works then you've got a node with a name property that isn't a String, and that's why the error
I wish to use the results of a UNION (n) as a filter for a subsequent match.
MATCH (n:Thing)-<<Insert valid match filters here>>
RETURN n
UNION
MATCH (n:Thing)-<<Insert a different set of match filters here>>
RETURN n;
n feeds into:
MATCH (n)-[:RELTYPE1]->(a:Artifact);
RETURN a;
I would expect to use a WITH statement, but I've struggled to figure out how structure the statement.
MATCH (n:Thing)-<<Insert valid match filters here>>
RETURN n
UNION
MATCH (n:Thing)-<<Insert a different set of match filters here>>
WITH n
MATCH (n)-[:RELTYPE1]->(a:Artifact);
RETURN a;
This was my original attempt, but the WITH is interpreted as the start of subquery of the UNION's second match (which makes sense).
I can see a few inelegant ways to make this work, but what is the proper approach?
I have been looking at your union example and it makes sense to me but I cannot see how I could make it work. But I am certainly not the guy with all of the answers. Is there a reason you couldn't do something like this though...
MATCH (n:Thing)
WHERE n.name = 'A'
WITH collect(n) as n1
MATCH (n:Thing)
WHERE n.name = 'B'
WITH n1 + collect(n) AS both
UNWIND both AS n
MATCH (n)-[:RELTYPE1]->(a:Artifact);
RETURN a;
It appears that LIKE is not supported in Cypher queries.
Is there any other construct that would perform the same task?
For instance:
start n = node(*) where n.Name LIKE('%SUBSTRING%') return n.Name, n;
using regular expressions:
http://neo4j.com/docs/developer-manual/current/#query-where-regex
start n = node(*) where n.Name =~ '.*SUBSTRING.*' return n.Name, n;
As of version 2.0, the preferred syntax uses MATCH.
e.g.
MATCH (n) where n.Name =~ '.*SUBSTRING.*' return n.Name, n;
No Regexps needed:
start n = node(*) where n.Name contains "substring" return n.Name, n;
Go to the cypher refcard and scroll down to the Predicates section. You will find this and other useful stuff.
Want case-insensitive? Convert to lower case:
start n = node(*) where lower(n.Name) contains lower("substring") return n.Name, n;
If you want to make it case insensitive
MATCH (n) WHERE n.name =~ '(?i).*SUBSTRING.*' RETURN n;