2014-10-06 68 views
0

我想使用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__屬性在我的代碼中設置?

回答

0

Volker,你是對的,默認的類型表示策略在這裏有點過度約束。

其實我們想要添加一個Relationship-TRS,它只是使用rel-type來映射到SDN,但我還沒有接受它。

你也可以只添加您的財產

@Indexed(unique=true) private String knownAsId; 

,然後構建這些關係,實體實例中的一個,並使用

template.save(relation); 

這也應該工作。

+0

謝謝,邁克爾。不幸的是,我的流量並不能保證我總是擁有已知的AsId。如果不知道源公司對目標公司的內部ID,我很可能可以得出這兩家公司之間的關係。並在稍後階段查明該ID是什麼。 – 2014-10-06 20:59:31

+0

在我的邏輯中,我想創建關係,如果它不存在並更新屬性,如果它。看起來去CREATE UNIQUE路由最簡單,因爲我所要做的就是更新屬性。另外,爲了創建關係,我不必查找兩端的節點,我需要的僅僅是組織ID(不是@GraphIds,而是公司節點的屬性)。 – 2014-10-06 21:08:28

相關問題