Search code examples
neo4jcypher

neo4j: cypher case and union


We are using neo4j v4.

I have USER, COMPUTER, COMPANY nodes(IBM, HP, DELL etc),

How can I make the HP_IBM case work(i.e. when u.preference is HP_IBM, I want the computers manufactured by both HP and IBM)?

MATCH (u:USER {id: 101})
RETURN  
CASE u.preference 
WHEN 'HP'    THEN  [(n:computer)-[r: MANUFACTURED_BY]->(c:HP) | n]
WHEN 'IBM'   THEN [(n:computer)-[r:ASSEMBELED_BY]->(c:IBM) | n] 
WHEN 'DELL'   THEN [(n:computer)-[r:ASSEMBELED_BY]->(c:DELL) | n] 
WHEN 'HP_IBM' THEN xxxxxxx END
AS result;

Any other queries/approaches are welcome!


Solution

  • Your schema can be modeled in a better way. Instead of having company names as Node Labels, you can store them as a part of the company node property let's say name. And instead of storing preferences as a concatenated String, you can store user-preferred companies in an array, like this: ["HP", "IBM"], now your cypher query becomes fairly simple, like this:

    MATCH (u:USER {id: 101})
    MATCH (n:computer)-[:MANUFACTURED_BY]->(c:Company)
    WHERE c.name IN u.preferences 
    RETURN n;
    

    If you want to keep the current schema itself, then try this:

    MATCH (u:USER {id: 101})
    RETURN  
    CASE u.preference 
    WHEN 'HP'    THEN  [(n:computer)-[r: MANUFACTURED_BY]->(c:HP) | n]
    WHEN 'IBM'   THEN [(n:computer)-[r:ASSEMBELED_BY]->(c:IBM) | n] 
    WHEN 'HP_IBM' THEN [(n:computer)-[r]->(c) WHERE ANY(x IN split(c.preference, '_') WHERE x IN labels(c)) | n] END
    AS result;
    

    Notice, that I have removed the relationship type from the path match because your relationship type varies with the company, so if your computer nodes are linked with the company, via a lot of distinct relationship types. This query might not work.