需要帮助将Neo4j Cypher请求转换为JPQL

时间:2015-06-01 09:39:14

标签: jpa neo4j cypher jpql

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

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

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

我们知道这个人适用于一个人(在极少数情况下很多人)Organisation s。

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

我们想要返回ResourceCategories“包含”此人可以使用的Software,因为不同组织之间可能存在关联,这使得他/她有权使用其他组织的软件。

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

  1. (:组织) - [* 0..2] - &GT;(:组织)
  2. (:组织) - [:possessesResource |:accessesResource |:supportsResource] - GT;(:软件)
  3. 第1点(:Organisation)-[*0..2]->(:Organisation)表示最多三个“组织”节点之间的可选关系。我们的想法是,在找到“组织”节点之后,我们也对所有路径感兴趣,这些路径最多来自与该人员所在组织相关联的其他两个“组织”。

    第2点(:Organisation)-[:possessesResource|:accessesResource|:supportsResource]->(: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((成员来自o1.possessesResource)或(成员来自o1.accessesResource)或(成员来自o1.supportsResource r))”?

    谢谢!

    更新:如JPQL doesn't support UNION,那我该如何重现“变长连接”?

1 个答案:

答案 0 :(得分:1)

很多工作之后,我们相信我们找到了相应的JPQL请求。

如果有人想知道如何模仿Cypher请求的困难部分,这是可变长度(Organisation)-[*0..2]->(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简单得多。希望它会成为一个标准,所以我不得不切换到关系数据库的原因有一天会消失。