Search code examples
neo4jcypher

Return node if relationship is not present


I'm trying to create a query using cypher that will "Find" missing ingredients that a chef might have, My graph is set up like so:

(ingredient_value)-[:is_part_of]->(ingredient)

(ingredient) would have a key/value of name="dye colors". (ingredient_value) could have a key/value of value="red" and "is part of" the (ingredient, name="dye colors").

(chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient)

I'm using this query to get all the ingredients, but not their actual values, that a recipe requires, but I would like the return only the ingredients that the chef does not have, instead of all the ingredients each recipe requires. I tried

(chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient)<-[:has_ingredient*0..0]-chef

but this returned nothing.

Is this something that can be accomplished by cypher/neo4j or is this something that is best handled by returning all ingredients and sorted through them myself?

Bonus: Also is there a way to use cypher to match all values that a chef has to all values that a recipe requires. So far I've only returned all partial matches that are returned by a chef-[:has_value]->ingredient_value<-[:requires_value]-recipe and aggregating the results myself.


Solution

  • Update 01/10/2013:

    Came across this in the Neo4j 2.0 reference:

    Try not to use optional relationships. Above all,

    don’t use them like this:

    MATCH a-[r?:LOVES]->() WHERE r IS NULL where you just make sure that they don’t exist.

    Instead do this like so:

    MATCH (a) WHERE NOT (a)-[:LOVES]->()
    

    Using cypher for checking if relationship doesn't exist:

    ...
    MATCH source-[r?:someType]-target
    WHERE r is null
    RETURN source
    

    The ? mark makes the relationship optional.

    OR

    In neo4j 2 do:

    ...
    OPTIONAL MATCH source-[r:someType]-target
    WHERE r is null
    RETURN source
    

    Now you can check for non-existing (null) relationship.