我想使用Spring-Data Neo4j在Neo4j中對包含公司及其業務關係的圖進行建模。所以我爲公司和邊緣創建了業務關係的節點。然而,有許多不同類型的關係(買方,供應商,製造商等等,以及一個通用版本「DOES_BUSINESS_WITH」)。每個關係只有一個屬性,即目標公司的源公司的內部ID,例如,買家擁有每個供應商的內部ID。而且每對公司在每個方向上只能有一種關係。使用Cypher和SDN @Query註釋創建Neo4J中的獨特路徑
我設置的方式是針對公司的@NodeEntity和針對不同業務關係的@RelationshipEntity。由於所有這些關係具有相同的性質,因爲它們都繼承了通用類,只需添加正確的標籤邊緣:
@RelationshipEntity(type="DOES_BUSINESS_WITH")
public class BusinessRelation {
@GraphId
private Long id;
@Fetch
@StartNode
private Company from;
@Fetch
@EndNode
private Company to;
@Indexed
private String knownAsId;
// getters and setters omitted
}
@RelationshipEntity(type="SUPPLIER")
public class SupplierRelation extends BusinessRelation {
public SupplierRelation() {
}
}
因爲我有不少的不同關係,我想用一個單一的存儲庫接口來處理他們全部。
現在,當我得到一個關係時,我想要在(現有的)公司之間創建一個新的關係,或者在必要時修改現有的關係。所以我決定去用CREATE UNIQUE暗號條款像這樣:
public interface BusinessRelationRepository extends GraphRepository<BusinessRelation> {
@Query(value="match (source:Company {orgId:{0}}),(target:Company {orgId:{1}}) create unique (source)-[r:SUPPLIER]->(target) return r", elementClass=SupplierRelation.class)
SupplierRelation createSupplierMarker(String sourceOrgId, String targetOrgId);
// ...
}
不幸的是,這將引發一個例外:
org.springframework.dao.DataRetrievalFailureException: No such property, '__type__'.; nested exception is org.neo4j.graphdb.NotFoundException: No such property, '__type__'.
at org.springframework.data.neo4j.support.Neo4jExceptionTranslator.translateExceptionIfPossible(Neo4jExceptionTranslator.java:66)
at org.springframework.data.neo4j.support.Neo4jTemplate.translateExceptionIfPossible(Neo4jTemplate.java:448)
at org.springframework.data.neo4j.support.Neo4jTemplate.doExecute(Neo4jTemplate.java:459)
at org.springframework.data.neo4j.support.Neo4jTemplate.access$000(Neo4jTemplate.java:87)
at org.springframework.data.neo4j.support.Neo4jTemplate$2.doInTransaction(Neo4jTemplate.java:471)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
at org.springframework.data.neo4j.support.Neo4jTemplate.exec(Neo4jTemplate.java:468)
at org.springframework.data.neo4j.repository.query.GraphRepositoryQuery.execute(GraphRepositoryQuery.java:82)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:421)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:381)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy65.createSupplierMarker(Unknown Source)
我希望加入elementClass中屬性的@Query註釋會給SDN足夠的信息將結果映射回所需的SupplierRelation,但事實並非如此。它實際上沒有任何影響。
我可以通過將__type__屬性添加到Cypher查詢中來解決這個問題,但是隨後我的代碼對Spring Data Neo4j的內部工作有了更多的瞭解。所以這個工程:
@Query(value="match (source:Company {orgId:{0}}),(target:Company {orgId:{1}}) create unique (source)-[r:SUPPLIER {__type__:\"SupplierRelation\"}]->(target) return r")
SupplierRelation createSupplierMarker(String sourceOrgId, String targetOrgId);
有沒有更好的解決方案,不需要我的__type__屬性在我的代碼中設置?
謝謝,邁克爾。不幸的是,我的流量並不能保證我總是擁有已知的AsId。如果不知道源公司對目標公司的內部ID,我很可能可以得出這兩家公司之間的關係。並在稍後階段查明該ID是什麼。 – 2014-10-06 20:59:31
在我的邏輯中,我想創建關係,如果它不存在並更新屬性,如果它。看起來去CREATE UNIQUE路由最簡單,因爲我所要做的就是更新屬性。另外,爲了創建關係,我不必查找兩端的節點,我需要的僅僅是組織ID(不是@GraphIds,而是公司節點的屬性)。 – 2014-10-06 21:08:28