Programmatically creating relationships between words in Neo4j using Cypher

I have a neo4j database filled with ~ 35K words in English. I want to create a relationship between words that differ by one letter at a given position in the word. i.e. (a) - (i) or (food) - (fool) or (cat) - (hat)

For words with one letter, the cypher query is pretty simple:

START n = node (), m = node (), where n.name = ~ '.' and m.name = ~ '.' and also NOT (n.name = m.name) create (n) - [: single_letter_change] โ†’ (m)

Building relationships for multilevel words is not easy, unfortunately. I know it is possible to create a collection as in:

C ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q' 'R', 'S', 'T', 'U', 'V', 'W' 'X', 'Y', 'Z'] ยท 9 letters AS

and I know that it is possible to iterate over a range with:

FOREACH (range i IN (0.25))

But everything I've put together seems to be ugly, dirty, and syntactically invalid. I'm sure there is an elegant way to do this in Cypher using collection functions, but I've spent a couple of days trying to figure it out and it's time to get help.

Ideas how to do this? I'll be happy to post some (invalid) cypher queries I've tried, but I'm afraid they might just confuse the problem.

EDIT: Here's an example that I was trying to establish a relationship for the first letters of two letter words, but I think it might be uncomfortable and I know it won't work:

WITH ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L ", 'M', 'N', 'O', 'P', 'Q' 'R', 'S', 'T', 'U', 'V', 'W' 'X', 'Y' 'Z'] AS alphabet FOREACH (first interval IN (0,25) | START n = node (), m = node (), where n.name = ~ (alphabet [{first}] + '.') And m .name = ~ (alphabet [{first}] + '.') and NOT (n.name = m.name) create (n) - [: single_letter_change] โ†’ (m)

+3


source to share


1 answer


This may use some tweaking, but I think it fits the bill



// match all the words, start with ones that are three characters long
match (w:Word)
where length(w.name) = 3
// create a collection the length of the matched word
with range(0,length(w.name)-1) as w_len, w
unwind w_len as idx
// iterate through the word and replace one letter at a time
// making a regex pattern
with "(?i)" + left(w.name,idx) + '.' + right(w.name,length(w.name)-idx-1) as pattern, w, w_len
// match the pattern against 3 letter words
// that are not the word
// not already like the word
// and match the pattern
match (new_word:Word)
where not (new_word = w) 
and not((new_word)-[:LIKE]-(w))
and length(new_word.name) = length(w_len)
and new_word.name =~ pattern
// create the relationship
create (new_word)-[:LIKE]->(w)
return new_word, w

      

+3


source







All Articles