Exclude (NodeA) if (NodeB) Contains Specific Text

Greetings,

Sorry if this is posted elsewhere, please point me in that direction if so.

I have a pattern of (a:NodeA)<--(b:NodeB). There can be a many node b to 1 node a. All have the same relationship type.
I want to exclude node a if any of the node b have a specific text.
Here's what I'm trying...

Match (x:NodeX {Title: 'SpecificTitle'})-[rt1:RelType1]->(y:NodeY)-[rt2:RelType2]->(a:NodeA)<-[rt2:RelType3]-(b:NodeB)
Where b.Title contains 'Specific Text'
Return x.Title, a.Title, b.Title

But this still returns the unwanted nodes a, it just doesn't return any node b with the specific text, I'm just filtering out certain nodes b.
I've also tried this...

Match (x:NodeX {Title: 'SpecificTitle'})-[rt1:RelType1]->(y:NodeY)-[rt2:RelType2]->(a:NodeA)<-[rt3:RelType3]-(b:NodeB)
With x,a, collect(b.Title) as bTitle
Where NOT bTitle contains 'Specific Text'
//Unwind bTitle as b   //optionally adding this line but still doesn't help
Return x.Title, a.Title, bTitle   // or b

But this returns no records.

Again the goal is to exclude all node a if any of the node b have a specific text. I just can't get my head around how to get this result.

Many thanks for any help!

Sorry, but I don’t understand your requirements. You have a pattern x->y->a<-b, without any constraints, so you are going to get every path in the database. Is this what you are looking for? What do you mean “filter out node a”? Node a is part of the pattern.

1 Like

Thanks for the response Gary! I'm sorry about the lack of info, I've provided a little more detail in my original, I'm trying to anonymize my data to some extent and maybe went too far in doing so. But there aren't really any more constraints needed than the ones I added.

Maybe some pics will help. Ultimately I want to return a list of NodeA but only if certain criteria are met. Here's one such criteria:

Match (x:NodeX {Title: 'SpecificTitle'})-->(y:NodeY)-->(a:NodeA)
Where Not (a)<--(:NodeB)
Return a

and I get many NodeA back that are not related to NodeB, this is good and no problem to return.
NoReltoNodeB

Now some of (a:NodeA) are related to (b:NodeB), but I only want to return certain (a:NodeA).
Here's an example of the (a:NodeA) I'm trying to exclude while keeping other (a:NodeA):

Match (x:NodeX {Title: 'SpecificTitle'})-->(y:NodeY)-->(a:NodeA)<--(b:NodeB)
Return a,b

This returns both a (orange) and b (green) nodes. Again, some of the a nodes I want to keep, and some I want to exclude, but I'm showing all the a nodes with this query.
FullNodeAReltoNodeB
In the pic above, see the red circle, there is one orange a node related to 5 green b nodes. Because one of the 5 b node titles has a 'Specific Text', I am hoping to filter on that specific text to help exclude/filter out that a node (and others in this same situation, where b node contains 'Specific Text').
But when I try to filter like so

Match (x:NodeX {Title: 'SpecificTitle'})-->(y:NodeY)-->(a:NodeA)<--(b:NodeB)
Where Not (b.Title) contains 'Specific Text'
Return a,b

I am not excluding/filtering out the desired a node, I am just filtering out the b node with the specific text. Where once there were 5 green nodes, there are now 4 green nodes
WhereOnlyFiltersNodeB

I hope this helps explain a bit better, please let me know if it does not.

Right and a:NodeA is part of the pattern because some of them I want to keep and some of them I want to exclude. Unless there's a way to get this 'exclude/keep' result where a:NodeA is not part of the pattern?

I think I understand...You want 1) all the 'a' nodes that have no relationship to a 'b' node, and 2) the 'a' nodes that have relationships to 'b' nodes that do not have a Title property that contains a specific text string. The following query should provide this result.

Match (x:NodeX {Title: 'SpecificTitle'})-->(y:NodeY)-->(a:NodeA)
Where Not Exists( (a)<--(:NodeB) )
Return a
UNION
Match (x:NodeX {Title: 'SpecificTitle'})-->(y:NodeY)-->(a:NodeA)<--(b:NodeB)
With a, collect(b) as bNodes
Where none(i in bNodes where i.Title contains 'Specific Text')
Return a

Is this what you are seeking?

1 Like
match (a:NodeA) where a.Title = 'SpecificTitle'
match (a1:NodeA)-[]-(b:NodeB) Where a1.Title <> a.Title
1 Like

Spot on, thank you so much Gary! If you have time, would you be able to dissect or point to documentation re:

Where none(i in bNodes where i.Title contains 'Specific Text')

Interesting that you can have a where inside a where?
The 'i' could be any variable 'looking through' the separate arrays of collected bNode Titles?
I see the use of none here in Predicate functions, but would be interested to know if anything as you've presented it exists in documentation.

Again, thank you for sticking with me through my explanations and arriving at a great solution.

Yes, that is a list predicate function. They return boolean values, so they can be used in 'where' predicates, as well as any place you can use an expression. I find these very useful. That is the documentation that I used to learn how to use them.

Your welcome...

1 Like

I just saw you asked to dissect the method. What it is doing is checking that NONE of the items in the bNodes list has the 'where' predicate evaluate to true. There are other predicate functions: 'all', 'single', and 'any'.

Basically, you define a variable ('I' in my case) that will loop through the items in the list ('bNodes' in my case). The 'where' predicate gets evaluated for each value of your variable ('I' in my case), which is used to calculate the method's return value of 'none', 'single', and 'any'. These are extremely powerful when you need to evaluate conditions on lists.

1 Like