需要帮助将 Neo4j Cypher 请求转换为 JPQL
Need help converting Neo4j Cypher request to JPQL
我有需要转换为 JPQL 的 Neo4j Cypher 请求:
MATCH (p:Person)-[:worksForOrganisation]->
(:Organisation)-[*0..2]->(:Organisation)
-[:possessesResource|:accessesResource|:supportsResource]->(:Software)
<-[:categoryContains]-(c:ResourceCategory)
WHERE id(p)=({personId})
RETURN c
此请求从具有标识符 personId
的唯一 Person
开始。
我们知道这个人为一个(在极少数情况下,很多)Organisation
工作。
我们知道每个组织都可以拥有、访问或支持类型为 Software
的资源。
我们希望 return ResourceCategories
"contain" Software
人可以使用,鉴于不同组织之间可能存在关联,授予 him/her 使用另一个组织的软件的权利。
将其转换为 JPQL 的困难来自:
- (:组织)-[*0..2]->(:组织)
- (:组织)-[:possessesResource|:accessesResource|:supportsResource]->(:Software)
点1:(:Organisation)-[*0..2]->(:Organisation)
表示最多三个"Organisation"节点之间的可选关系。这个想法是,找到一个 "Organisation" 节点后,我们还对从至多两个其他 "Organisations" 开始的所有路径感兴趣,这些路径与该人所工作的组织相关联。
点2 : (:Organisation)-[:possessesResource|:accessesResource|:supportsResource]->(:Software)
表示,找到一个"Organisation",可以关联到一个"Software",有3种关系(或者甚至是各种不同的关系)。
到目前为止我的想法(真的不完整,我知道):
@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))"吗?
谢谢!
UPDATE :如 JPQL doesn't support UNION,那么我该如何重现 "variable length join"?
经过大量 的工作,我们相信我们找到了相应的 JPQL 请求。
如果有人想知道如何模拟 Cypher 请求的困难部分,即可变长度的路径 (Organisation)-[*0..2]->(Organisation)
,我相信我们在 JPQL 中根本无法做到,我们必须对待所有超级 class "Organisation" 的可能实例是 "Community"、"Institution"、"TeachingDepartment" 和 "AdministrativeDepartment".
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 简单得多。希望它会成为一个标准,所以我不得不切换到关系数据库的原因有一天会消失。
我有需要转换为 JPQL 的 Neo4j Cypher 请求:
MATCH (p:Person)-[:worksForOrganisation]->
(:Organisation)-[*0..2]->(:Organisation)
-[:possessesResource|:accessesResource|:supportsResource]->(:Software)
<-[:categoryContains]-(c:ResourceCategory)
WHERE id(p)=({personId})
RETURN c
此请求从具有标识符 personId
的唯一 Person
开始。
我们知道这个人为一个(在极少数情况下,很多)Organisation
工作。
我们知道每个组织都可以拥有、访问或支持类型为 Software
的资源。
我们希望 return ResourceCategories
"contain" Software
人可以使用,鉴于不同组织之间可能存在关联,授予 him/her 使用另一个组织的软件的权利。
将其转换为 JPQL 的困难来自:
- (:组织)-[*0..2]->(:组织)
- (:组织)-[:possessesResource|:accessesResource|:supportsResource]->(:Software)
点1:(:Organisation)-[*0..2]->(:Organisation)
表示最多三个"Organisation"节点之间的可选关系。这个想法是,找到一个 "Organisation" 节点后,我们还对从至多两个其他 "Organisations" 开始的所有路径感兴趣,这些路径与该人所工作的组织相关联。
点2 : (:Organisation)-[:possessesResource|:accessesResource|:supportsResource]->(:Software)
表示,找到一个"Organisation",可以关联到一个"Software",有3种关系(或者甚至是各种不同的关系)。
到目前为止我的想法(真的不完整,我知道):
@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))"吗?
谢谢!
UPDATE :如 JPQL doesn't support UNION,那么我该如何重现 "variable length join"?
经过大量 的工作,我们相信我们找到了相应的 JPQL 请求。
如果有人想知道如何模拟 Cypher 请求的困难部分,即可变长度的路径 (Organisation)-[*0..2]->(Organisation)
,我相信我们在 JPQL 中根本无法做到,我们必须对待所有超级 class "Organisation" 的可能实例是 "Community"、"Institution"、"TeachingDepartment" 和 "AdministrativeDepartment".
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 简单得多。希望它会成为一个标准,所以我不得不切换到关系数据库的原因有一天会消失。