Replace regular expressions in cypher - neo4j

I can search for regular expressions in cypher
MATCH (n:model) WHERE n.name =~ '.*&.*;.*' RETURN n.name
but can I also replace them? I would like to write something like
MATCH (n:model) RETURN replace(n.name, ~'&.*;', '_');

There is a replace function in cypher, but it does not replace regexps, just simple strings.
Maybe a feature request for replaceRegex could be done?
An workaround would be to do this programatically, after you return the names (if you use call cypher queries from another application).

Related

Cypher: how to use a regex in shortcut match expression?

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

Cypher query: CONCAT and TOKENIZE in the SET clause

I need to generate a cypher query where I should SET the value of one property based on the value of the other property as like this -
MATCH (n) SET n.XXX = n.YYY return n;
So XXX will be set to YYY. But YYY has values like this - "ABCD.net/ABC-MNO-XYZ-1234" and I should eliminate all the special characters (/,- etc) and then concat the splitted substrings. So the logical statement should be like -
MATCH (n) SET n.XXX = CONCAT(SPLIT(n.YYY, "/")) return n;
Neo4j doesn't have any CONCAT function. So how is it possible to accomplish this stuff in a cypher query?
Any help will be highly appreciated.
Thanks
You could do this:
MATCH (n:SomeNode) set n.uuid = reduce(s="",x in split(n.uuid,'/')| s+x)
and run this query for every special character.
If there are a lot of special characters, write this query:
UNWIND ['/','#'] as delim match (n:SomeNode) set n.uuid = reduce(s="",x in split(n.uuid,delim)| s+x)
Replace '/','#' with a list of your special characters.
Your use case really looks like you want removal of characters in the string, and neo4j does offer a replace() function that you can leverage for this.
But in the event that you do want a join(), the APOC Procedures library has this among the text functions it offers.

How to do trigram / fuzzy match in neo4j cypher?

I was using postgreSQL which has show_trgam() and similarity(). I am new to neo4j and wanna do fuzzy comparison of two strings. It will be great if the comparison would return a score.
Any response is appreciated.
If i understand your problem correctly.
You can use regular expression to compare values in neo4j.
Like
MATCH (n)
WHERE n.name =~ '(?i).*searchString.*'
RETURN n
It will return result with matching sub string.
You can have detail documentation about this here-
http://docs.neo4j.org/chunked/milestone/query-where.html#_regular_expressions

Function to get position of substring, using backreferences in Neo4j Cypher regex

I'm using the web interface and Neo4j Community 2.1.3.
Is there a Cypher function or combination of functions that gives the position of a substring in a string or uses its location as a starting point for a SET clause, similar to FIND or SEARCH in Google Spreadsheets or substring-before() and substring-after() in XPATH? Something like:
MATCH (p)
WHERE p.name=~"^.*?\\, .*?$"
SET p.lastName=LEFT(p.name,FIND(p.name,", ")), p.firstName=RIGHT(p.name,FIND(p.name,",")+1)
RETURN p ;
The FIND() function would return the position of the substring (in this case: a comma plus single space), so the LEFT and RIGHT functions can be used to extract a partial string. Something like the XPATH substring-before() and substring-after() accomplish the same thing in one function. The Cypher string functions SUBSTRING, LEFT, RIGHT are only of limited use without this additional functionality — unless I'm just missing something.
Along these lines (string manipulation), is there a way to use backreferences to Cypher regex WHERE matches? We can use groups for matching, but I can't figure out how to reuse those groups using \1 or $1 in a SET clause. The above code could be made simpler using regex groups and some kind of backreferences:
MATCH (p)
WHERE p.name=~"^(.*?)\\, (.*?)$"
SET p.lastName=\1, p.firstName=\2
RETURN p ;
Are these things possible yet? I can't find documentation or examples. I've seen the Regx4Neo plugin, but the command shell is beyond my abilities at this point.
If your example is so contrived that this is irrelevant, my apologies, but you could just split on ", " and then SET properties equal to the different elements resulting from the split. So, with the following example data:
CREATE (:Person {name:'White, Nicole'}),
(:Person {name:'Bastani, Kenny'}),
(:Person {name:'Hunger, Michael'})
We can get first and last names and set them as properties:
MATCH (p:Person)
WITH p, SPLIT(p.name, ", ") AS names
SET p.firstName = names[1],
p.lastName = names[0]
Result:
MATCH (p:Person)
RETURN p.firstName, p.lastName
p.firstName p.lastName
Nicole White
Kenny Bastani
Michael Hunger

Running a case-insensitive cypher query

Is it possible to run a case-insensitive cypher query on neo4j?
Try that: http://console.neo4j.org/
When I type into this:
start n=node(*)
match n-[]->m
where (m.name="Neo")
return m
it returns one row. But when I type into this:
start n=node(*)
match n-[]->m
where (m.name="neo")
return m
it does not return anything; because the name is saved as "Neo". Is there a simple way to run case-insensitive queries?
Yes, by using case insensitive regular expressions:
WHERE m.name =~ '(?i)neo'
https://neo4j.com/docs/cypher-manual/current/clauses/where/#case-insensitive-regular-expressions
Another way would be:
WHERE LOWER(m.Name) = LOWER("Neo")
And if you are using the Neo4j Client (.NET):
Client.Cypher.Match("(m:Entity)")
.Where("LOWER(m.Name) = LOWER({name})")
.WithParam("name", inputName)
.Return(m => m.As<Entity>())
.Results
.FirstOrDefault();
If anybody is looking on how to do this with a parameter, I managed to do it like this.
query = "{}{}{}".format('Match (n) WHERE n.pageName =~ "'"(?i)", name, '" RETURN n')
and "name" is the variable or your parameter
You can pass a parameter to the case insensitive regular expression like:
WHERE m.name =~'(?i)({param})

Resources