首页 文章

如果不存在关系,则返回节点

提问于
浏览
62

我正在尝试使用cypher创建一个查询,它将“查找”厨师可能缺少的成分,我的图形设置如下:

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

(ingredient) 将具有name = "dye colors"的键/值 . (ingredient_value) 可以具有值= "red"和"is part of" (ingredient, name="dye colors") 的键/值 .

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

我正在使用此查询来获取食谱所需的所有 ingredients ,但不是它们的实际值,但我希望仅返回厨师没有的 ingredients ,而不是每个食谱所需的所有成分 . 我试过了

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

但这没有任何回报 .

这是可以通过cypher / neo4j完成的事情,还是通过返回所有成分并通过它们自行排序来最好地处理这个问题?

额外奖励:还有一种方法可以使用cypher来匹配厨师拥有的所有值以及配方所需的所有值 . 到目前为止,我只返回了 chef-[:has_value]->ingredient_value<-[:requires_value]-recipe 返回的所有部分匹配并自行汇总结果 .

6 回答

  • 2

    Update 01/10/2013:

    在Neo4j 2.0 参考中遇到过这个:

    尽量不要使用可选关系 . 首先,

    don’t use them like this:

    MATCH a-[r?:LOVES]->() WHERE r IS NULL 你只是确保它们不存在 .

    Instead do this like so:

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

    使用cypher检查关系是否不存在:

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

    的? mark使关系成为可选的 .

    要么

    在neo4j 2中:

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

    现在您可以检查不存在的(null)关系 .

  • 6

    用于获取没有任何关系的节点

    这是检查关系是否存在的好选择

    MATCH (player)-[r:played]->()
        WHERE r IS NULL 
        RETURN player
    

    您还可以检查多个条件 . 它将返回所有节点,这些节点没有“播放”或“未播放”关系 .

    MATCH (player) 
     WHERE NOT (player)-[:played|notPlayed]->()
     RETURN player
    

    获取没有任何实现的节点

    MATCH (player) 
    WHERE NOT (player)-[r]-()
    RETURN player
    

    它将检查节点没有任何传入/传出关系 .

  • 2

    如果您需要“条件排除”语义,您可以通过这种方式实现它 .

    从neo4j 2.2.1开始,您可以使用 OPTIONAL MATCH 子句并过滤掉不匹配的( NULL )节点 .

    OPTIONAL MATCHWHERE 子句之间使用 WITH 子句也很重要,这样第一个 WHERE 定义了可选匹配的条件,第二个 WHERE 就像过滤器一样 .

    假设我们有两种类型的节点: PersonCommunication . 如果我想让所有从未通过电话沟通但可能已通过其他方式传达的人员,我会提出以下问题:

    MATCH (p: Person) 
    OPTIONAL MATCH p--(c: Communication) 
    WHERE c.way = 'telephone'
    WITH p, c 
    WHERE c IS NULL 
    RETURN p
    

    匹配模式将匹配所有人与他们的通信,其中 cNULL 用于非电话通信 . 然后过滤器( WITH 之后的 WHERE )将过滤掉所有其他电话通信 .

    参考文献:

    http://neo4j.com/docs/stable/query-optional-match.html#_introduction_3 http://java.dzone.com/articles/new-neo4j-optional

  • 12

    我写了一篇关于如何使用Cypher 2.0自然地完成这一工作的要点

    http://gist.neo4j.org/?9171581

    关键点是对可用成分使用可选匹配,然后比较过滤缺失(无效)成分或成分的错误值 .

    请注意,这个概念是声明性的,不需要描述算法,只需写下您需要的内容即可 .

  • 117

    我使用gremlin完成了这个任务 . 我做到了

    x=[]
    
    g.idx('Chef')[[name:'chef1']].as('chef')
    .out('has_ingredient').as('alreadyHas').aggregate(x).back('chef')
    .out('has_value').as('values')
    .in('requires_value').as('recipes')
    .out('requires_ingredient').as('ingredients').except(x).path()
    

    这返回了所有缺失成分的路径 . 我无法用密码语言来表达这一点,至少对于1.7版本 .

  • 2

    最后一个查询应该是:

    START chef = node(..)
    MATCH (chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient)
    WHERE (ingredient)<-[:has_ingredient]-chef
    RETURN ingredient
    

    这种模式: (ingredient)<-[:has_ingredient*0..0]-chef

    是它没有返回任何东西的原因 . *0..0 表示关系的长度必须为零,这意味着成分和厨师必须是同一个节点,而它们不是 .

相关问题