【问题标题】:Need help converting Neo4j Cypher request to JPQL需要帮助将 Neo4j Cypher 请求转换为 JPQL
【发布时间】:2015-06-04 00:41:26
【问题描述】:

我有需要转换为 JPQL 的 Neo4j Cypher 请求:

MATCH (p:Person)-[:worksForOrganisation]->
    (:Organisation)-[*0..2]->(:Organisation)
    -[:possessesResource|:accessesResource|:supportsResource]->(:Software)
    <-[:categoryContains]-(c:ResourceCategory)
WHERE id(p)=({personId})
RETURN c

此请求从唯一的Person 开始,标识符为personId

我们知道此人为一个(在极少数情况下,很多)Organisations 工作。

我们知道每个组织都可以拥有、访问或支持Software 类型的资源。

鉴于不同组织之间可能存在关联,我们希望返回“包含”该人可以使用的Softwares 的ResourceCategories,从而授予他/她使用来自另一个组织。

将其转换为 JPQL 的困难来自:

  1. (:组织)-[*0..2]->(:组织)
  2. (:组织)-[:possessesResource|:accessesResource|:supportsResource]->(:软件)

第 1 点(:Organisation)-[*0..2]-&gt;(:Organisation) 表示最多三个“组织”节点之间的可选关系。这个想法是,在找到一个“组织”节点后,我们还对从最多两个其他“组织”开始的所有路径感兴趣,这些“组织”与该人所在的组织相关联。

第 2 点(:Organisation)-[:possessesResource|:accessesResource|:supportsResource]-&gt;(:Software) 表示,找到一个“组织”后,它可以与具有三种关系的“软件”相关联(甚至可以通过多种关系)。

到目前为止我的想法(我知道真的不完整):

@Query("SELECT rc FROM Person p, Organisation o1, Organisation o2, Organisation o3, Software s, ResourceCategory rc " +
        "WHERE p.id = :personId " +
        "AND o1 MEMBER OF p.worksForOrganisations " +
        "AND s MEMBER OF rc.resources")
Set<ResourceCategoryEntity> getCategoriesForPerson(@Param("personId") Long personId);

问题

  • 如何重现 [*0..2] 可选关系?我是否需要在三个请求之间使用 UNION,一个仅包含组织 o1,第二个包含组织 o1 和 o2,最后一个包含组织 o1、o2 和 o3?
  • 各种关系能否转换为“AND ((s MEMBER OF o1.possessesResource) OR (s MEMBER OF o1.accessesResource) OR (s MEMBER OF o1.supportsResource r))”?

谢谢!

更新:作为JPQL doesn't support UNION,那么如何重现“可变长度连接”?

【问题讨论】:

  • 您说要将其转换为 SQL,然后继续讨论 JPQL。最好决定哪个是你的目标
  • 好的,我修正了我的消息,它是 JPQL。

标签: jpa neo4j cypher jpql


【解决方案1】:

经过大量工作,我们相信我们找到了相应的 JPQL 请求。

如果有人想知道如何模仿 Cypher 请求的困难部分,即可变长度路径 (Organisation)-[*0..2]-&gt;(Organisation),我相信我们在 JPQL 中根本无法做到,我们必须处理所有可能的实例超类“组织”,分别是“社区”、“机构”、“教学部门”和“行政部门”。

SELECT DISTINCT (rc) FROM ResourceCategory rc JOIN rc.resources d
WHERE d.id IN ( SELECT e.id FROM Documentation e, Organisation o, Person u
                WHERE u.id = :personId
                  AND o MEMBER OF u.worksForOrganisations
                  AND (   o = e.organisationPossessingResource
                       OR o = e.organisationSupportingResource
                       OR o MEMBER of e.organisationsHavingAccessToResource
                      )
              )
   OR d.id IN ( SELECT d.id FROM Documentation d, Organisation o
                WHERE TYPE(o) IN (Institution)
                  AND (   o = d.organisationPossessingResource
                       OR o = d.organisationSupportingResource
                       OR o MEMBER of d.organisationsHavingAccessToResource
                      )
                  AND o.id IN (
                     SELECT i.id FROM Institution i, AdministrativeDepartment ad, Person u
                     WHERE u.id = :personId
                       AND ad MEMBER OF u.worksForOrganisations
                       AND ad MEMBER OF i.administrativeDepartments
                     )
               )
   OR d.id IN ( SELECT d.id FROM Documentation d, Organisation o
                WHERE TYPE(o) IN (Institution)
                  AND (   o = d.organisationPossessingResource
                       OR o = d.organisationSupportingResource
                       OR o MEMBER of d.organisationsHavingAccessToResource
                      )
                  AND o.id IN (
                     SELECT i.id FROM Institution i, TeachingDepartment td, Person u
                     WHERE u.id = :personId
                       AND td MEMBER OF u.worksForOrganisations
                       AND td MEMBER OF i.teachingDepartments
                     )
              )
   OR d.id IN ( SELECT d.id FROM Documentation d, Organisation o
                WHERE TYPE(o) IN (Community)
                  AND (   o = d.organisationPossessingResource
                       OR o = d.organisationSupportingResource
                       OR o MEMBER of d.organisationsHavingAccessToResource
                      )
                  AND o.id IN (
                     SELECT c.id FROM Community c, Institution i, AdministrativeDepartment ad, Person u
                     WHERE u.id = :personId
                       AND ad MEMBER OF u.worksForOrganisations 
                       AND ad MEMBER OF i.administrativeDepartments
                       AND c MEMBER OF i.communities
                     )
              )
   OR d.id IN ( SELECT d.id FROM Documentation d, Organisation o
                WHERE TYPE(o) IN (Community)
                  AND (   o = d.organisationPossessingResource 
                       OR o = d.organisationSupportingResource 
                       OR o MEMBER of d.organisationsHavingAccessToResource
                      )
                  AND o.id IN (
                     SELECT c.id FROM Community c, Institution i, TeachingDepartment td, Person u
                     WHERE u.id = :personId
                       AND td MEMBER OF u.worksForOrganisations
                       AND td MEMBER OF i.teachingDepartments
                       AND c MEMBER OF i.communities
                  )
              )
   OR d.id IN ( SELECT d.id FROM Documentation d, Organisation o
                WHERE TYPE(o) IN (Community)
                  AND (   o = d.organisationPossessingResource
                       OR o = d.organisationSupportingResource
                       OR o MEMBER of d.organisationsHavingAccessToResource
                      )
                 AND o.id IN (
                     SELECT c.id FROM Community c, Institution i, Person u 
                     WHERE u.id = :personId 
                       AND i MEMBER OF u.worksForOrganisations 
                       AND i MEMBER OF c.institutions
                     )
              )

脚注:这表明 Cypher 绝对摇滚,比等效的 JPQL 简单得多。希望它会成为一种标准,所以我不得不切换到关系数据库的原因有一天会消失。

【讨论】:

    猜你喜欢
    • 2019-10-16
    • 2020-07-28
    • 1970-01-01
    • 1970-01-01
    • 2011-03-25
    • 2015-01-17
    • 1970-01-01
    • 2018-11-24
    • 2019-12-23
    相关资源
    最近更新 更多