如何构造CYPHER查询以返回不存在的路径和没有现有节点的不同结果

时间:2016-02-24 12:36:47

标签: node.js neo4j cypher

在我的应用程序中,我设置了角色,为用户提供对其他用户资产的不同级别的访问权限。

我有此查询返回资产BobsPrivate,其中请求的用户是Bob

     MATCH (u:User {name: 'Bob' })
     MATCH (n:Asset:Album {name:'BobsPrivate'})
     WHERE (u)-[:CREATED|:FRIENDS_CAN_READ]->(n) OR (n)<-[:CAN_READ]-()<-[:BELONGS_TO]-(u)
     RETURN n

我的所有查询都来自节点的REST API。

这按预期工作并返回资产,因为其中一个关系存在,如果我传递一个不存在的资产名称,如foo,它按预期工作,不返回任何内容。

当我传递用户JamesBobsPrivate时,它也没有返回任何内容,正如您所期望的那样,但我希望返回不同的内容。

我的问题是,我得到了与不存在的资产相同的结果,并且与后者不存在的关系等同于没有适当的访问级别。

如何构造我的查询,以便我可以返回两个不同的结果,以便我可以在我的控制器中以不同的方式处理HTTP响应(404,403)?我还需要在UPDATEDELETE方法中使用相同的原则。

编辑:

我稍微更改了我的查询,它给了我正在寻找的内容,但它确实引入了另一个MATCH,所以我仍然愿意接受建议

    OPTIONAL MATCH (u:User {name: 'Bob' })
    OPTIONAL MATCH (n:Asset:Album {name:'BobsPrivate'})
    WHERE (u)-[:CREATED|:FRIENDS_CAN_READ]->(n) OR (n)<-[:CAN_READ]-()<-[:BELONGS_TO]-(u)
    WITH n
    OPTIONAL MATCH (l:Asset:Album {name:'BobsPrivate'})
    RETURN n AS ASSET, l IS NOT NULL AS ASSET_EXISTS, CASE WHEN n IS NOT NULL AND l IS NOT NULL THEN true ELSE

这让我做的是按原样返回Asset,而不需要根据关系进行任何额外的向下钻取,这样我就可以返回一个有用的布尔值,我的控制器可以使用它。

我是NEO4J的新手,我很确定会有更好的方式,所以如果你知道的话,我会非常感激。

1 个答案:

答案 0 :(得分:1)

我尝试达到预期行为的5分钟:

MATCH (u:User {name: 'Bob' })
MATCH (n:Asset:Album {name:'BobsPrivate'})
RETURN 
  n, 
  EXISTS((u)-[:CREATED|:FRIENDS_CAN_READ]->(n)) as isDirectAccessible,
  EXISTS((n)<-[:CAN_READ]-()<-[:BELONGS_TO]-(u)) as isIndirectAccessible

我们正在分别检索所有事实:

  • 资产
  • 返回布尔标志,是否可以直接访问资产
  • 返回布尔标志,是否可以间接访问资产

然后,在客户端,我们可以决定我们将如何处理。例如:

  • 如果根本没有返回任何数据:return 404
  • 如果数据库中有此类资产,但其中一个(或两个)标志为false:return 403
  • 如果资产存在,则两个标志都为真:返回200和数据

删除查询示例:

MATCH (u:User {name: 'Bob' })
MATCH (n:Asset:Album {name:'BobsPrivate'})
WITH 
  n, 
  EXISTS((u)-[:CREATED|:FRIENDS_CAN_READ]->(n)) as isDirectAccessible,
  EXISTS((n)<-[:CAN_READ]-()<-[:BELONGS_TO]-(u)) as isIndirectAccessible
WITH n, isDirectAccessible, isIndirectAccessible, 
  (CASE
    WHEN isDirectAccessible OR isIndirectAccessible THEN n
    ELSE null
    END) as deletableObject
DETACH DELETE deletableObject
RETURN (deletableObject IS NOT NULL) as isDeleted, isDirectAccessible, isIndirectAccessible

同样的原则在这里工作:

  • 如果没有返回,则资产不存在
  • 如果有什么东西返回:检查标志

注意:我觉得这可能不是最好的方法。但是,嘿,它有效。