Karuzo Rodriguez
Karuzo Rodriguez

Reputation: 25

Neo4j Cypher exclude nodes where a specific relationship is missing

I am trying to implement a fraud detection system in neo4j, where I have a bunch of nodes with person, bank account, kredit card, telephone numbers and addresses.

A basic idea of detecting fraud in bank sytems is someone who has a bank account and a credit card, where his credit card is not linked to his own bank account.

And I cannot figure it out what to do. Because when I try to exclude these nodes with: WHERE NOT (k)-[:VERKNUEPFT]-(b) I still get the wrong nodes, but it just hides the VERKNUEPFT node.

Can someone give me the correct way to negate, to exclude every not needed node?

So simply said I need to get following output: expected output

First I filtered out which nodes are needed at all: MATCH (p:person)-[r:HAT_KONTO]->(b:bankkonto), (p)-[r2:NUTZT_KARTE]->(k:kreditkarte) return p,b,k,r,r2; which gives me the following: full result the nodes below this Hermine and Ron are correct, so I want to exclude everything who are linked to them.

But when I try to do MATCH (p:person)-[r:HAT_KONTO]->(b:bankkonto), (p)-[r2:NUTZT_KARTE]->(k:kreditkarte) WHERE NOT (k)-[:VERKNUEPFT]-(b) return p,b,k,r,r2;

I get the following: full result, excluded specific linking

only the bankaccount (the brown one) is missing.

When I test the same code with WHERE instead of WHERE NOT: MATCH (p:person)-[r:HAT_KONTO]->(b:bankkonto), (p)-[r2:NUTZT_KARTE]->(k:kreditkarte) WHERE (k)-[:VERKNUEPFT]-(b) return p,b,k,r,r2;

reverted of what I want to achieve

I achieve the opposite of what I want to.

Upvotes: 0

Views: 68

Answers (1)

Charchit Kapoor
Charchit Kapoor

Reputation: 9284

I think you need to check, whether all the credit cards held by a person, are linked to any one of his bank accounts. Currently, you are checking if they are linked to a specific bank. Try something along these lines:

MATCH (p:person)-[:HAT_KONTO]->(b:bankkonto)
WITH p, collect(b) AS banks
MATCH (p)-[r2:NUTZT_KARTE]->(k:kreditkarte)
WITH p, banks, collect(k) AS creditCards 
WHERE ALL(card IN creditCards WHERE ANY(bank IN banks WHERE (card)-[:VERKNUEPFT]-(bank)))
UNWIND banks AS b
UNWIND creditCards AS k
MATCH (p)-[r:HAT_KONTO]->(b), (p)-[r2:NUTZT_KARTE]->(k)
RETURN p,r,b,r2,k

In the above query, we first collect the banks associated with a person and his/her credit cards into two different collections. Then, we check whether all the credit cards are linked to one of the banks, to filter out the valid users. Then we return their details.

Upvotes: 0

Related Questions