cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

How to find a pattern in each element of a list

wfarin
Node Link

Hello,

I have a very beginner question but I didn't find any solution in tutorials and forum.

I would like to search a pattern in a list of strings. Below the 'n.name' is only a string and I would like to do the same operation but on a list.

MATCH (n:Person)
WHERE n.name =~ '(?i)AND.*'
RETURN n.name, n.age

I see how to find a exact value in list with (but not with a matching pattern):

MATCH (n:Person)
WHERE "VALUE" IN n.name
RETURN n.name, n.age

Thank you very much and sorry if the question was already asked.
William

1 ACCEPTED SOLUTION

When you have a node with a list property, you can use list predicate functions to test if any, all, or none of the elements of the list meet a predicate.

So in your case, something like this may work:

MATCH (n:Person)
WHERE any(name in n.name WHERE name =~ '(?i)AND.*')
RETURN n.name, n.age

Note that this approach will not leverage indexes. If you do need to leverage indexes like this, you may have to consider restructuring your data model with new kinds of nodes, such as :Alias nodes attached to a :Person, each one with a name (that is indexed), and have your query do an index lookup on the alias name using a lookup that will utilize the index, then MATCH to the :Person nodes for that alias.

View solution in original post

6 REPLIES 6

MuddyBootsCode
Graph Steward

Well you can collect that attributes you want in a list like this:

MATCH (n:Person)
with collect(n.names) as names
UNWIND names a n
where n.name =~ <YOUR LOGIC HERE>

This will return you a list a names that you can then UNWIND or loop through and perform your operations on them.

Thank you very much for the help.
However, when I try this to my dataset, i got an error that let me think I cannot use WHERE after UNWIND.

Also these two queries give the same result that I was not expecting

QUERY 1

MATCH (n:Person)
with collect(n.names) as names
UNWIND names as n
return n

QUERY 2

MATCH (n:Person)
return n.names

Screen of these two examples.
Query without unwind
2X_f_f68c8e0fb3661abb705ebd345e0650d80041ec19.png

QUERY with unwind
2X_3_3d1c82321f166af17a7c7190f68fdd3c6df1b98c.png

I was expecting 'collect' to unroll all the element and put it in a simple list whereas this is still a list of list of string.

MuddyBootsCode
Graph Steward

You can interact with the list after each collect. So you can use WHERE for sure. There are some other APOC methods you can use as well.

intouch_vivek
Graph Steward

@wfarin

Logic for Manipulation in List
MATCH (n:Person)
with collect( distinct n) as names
with [name in names where name.name=~'B' or name.name=~'A'] as name
return name

When you have a node with a list property, you can use list predicate functions to test if any, all, or none of the elements of the list meet a predicate.

So in your case, something like this may work:

MATCH (n:Person)
WHERE any(name in n.name WHERE name =~ '(?i)AND.*')
RETURN n.name, n.age

Note that this approach will not leverage indexes. If you do need to leverage indexes like this, you may have to consider restructuring your data model with new kinds of nodes, such as :Alias nodes attached to a :Person, each one with a name (that is indexed), and have your query do an index lookup on the alias name using a lookup that will utilize the index, then MATCH to the :Person nodes for that alias.

Thanks very much for the queries. I will try them when my server is back and will let you know if it works.