Neo4j and Relationships

26 views
Skip to first unread message

Angelo Immediata

unread,
Dec 19, 2013, 1:52:58 PM12/19/13
to ne...@googlegroups.com
Hi there

I'm using this environment:
  • neo4j 1.9.5
  • spring 3.2.6
  • spring neo4j 2.3.3
I'm pretty new to graph DB so I need some suggestions from experts

I'ld like to use the relationship direction in order to implement the following scenario: I have a graph where noder have only one type of relationship but each relationship can have a direction; let's suppose to call the type of the relationship "ROAD_ELEMENT" and let's suppose we have the following nodes: A, B, C and D and let's suppose the A is related to B, C is related to A and D and A are related between them; I'ld like to represent this scenario by using the relationship type "RELATION" in this way:
  • A-->B (relationship of type "ROAD_ELEMENT" and direction "OUTCOMING" from point A)
  • A<--C (relationship of type "ROAD_ELEMENT" and direction "INCOMING" from point A)
  • A<-->D (relationship of type "ROAD_ELEMENT" and direction "BOTH" from point A)
The final objective of my data-modeling is the following: I need to indicate that I can only walk from A to B and not from B to A, I only can walk from C to A but not from A to C and I can walk both from A to D and from D to A; in this way when I search for the minimal path between 2 nodes os a graph by using the neo4j alghoritms (e.g. dijkstra, shortestPath etc...), in the result I must avoid to have a path starting from the point B to the point A (I can only navigate from A to B)

The first question I'ld like to do is: is it correct that I represent my scenario in the way I wrote (that is by using the relationship direction information in order to know how I can navigate my own graph)? Is there any other technique I can use in order to implement my scenario?

In order to represent this scenario I wrote the following Java classes (using the spring annotation):
Node class
@NodeEntity
public class GraphNode {
//Id del nodo in neo4j
@GraphId
private Long nodeId;
//Id del record nel DB Postgres
@Indexed(indexName="GIUNZIONE_DB_ID",unique=true,numeric=false)
private String giunzioneDbId;
@Indexed(indexName="COORDINATA_X",unique=false,numeric=true)
private double x;
@Indexed(indexName="COORDINATA_Y",unique=false,numeric=true)
private double y;
@Indexed(indexName="COORDINATA_Z",unique=false,numeric=true)
private double z;
@Indexed(indexName="COORDINATA_M",unique=false,numeric=true)
private double m;
@RelatedToVia(direction=Direction.INCOMING,elementClass=GraphNodesRelationship.class)
private Set<GraphNodesRelationship> versoCareggiataDiscorde = new HashSet<GraphNodesRelationship>();
@RelatedToVia(direction=Direction.OUTGOING,elementClass=GraphNodesRelationship.class)
private Set<GraphNodesRelationship> versoCareggiataConcorde = new HashSet<GraphNodesRelationship>();
@RelatedToVia(direction=Direction.BOTH, elementClass=GraphNodesRelationship.class)
private Set<GraphNodesRelationship> versoCareggiataDoppio = new HashSet<GraphNodesRelationship>();
public Long getNodeId() {
return nodeId;
}
public void setNodeId(Long nodeId) {
this.nodeId = nodeId;
}
public String getGiunzioneDbId() {
return giunzioneDbId;
}
public void setGiunzioneDbId(String giunzioneDbId) {
this.giunzioneDbId = giunzioneDbId;
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
public double getZ() {
return z;
}
public void setZ(double z) {
this.z = z;
}
public double getM() {
return m;
}
public void setM(double m) {
this.m = m;
}
public Set<GraphNodesRelationship> getVersoCareggiataDiscorde() {
return versoCareggiataDiscorde;
}
public void setVersoCareggiataDiscorde(Set<GraphNodesRelationship> versoCareggiataDiscorde) {
this.versoCareggiataDiscorde = versoCareggiataDiscorde;
}
public Set<GraphNodesRelationship> getVersoCareggiataConcorde() {
return versoCareggiataConcorde;
}
public void setVersoCareggiataConcorde(Set<GraphNodesRelationship> versoCareggiataConcorde) {
this.versoCareggiataConcorde = versoCareggiataConcorde;
}
public Set<GraphNodesRelationship> getVersoCareggiataDoppio() {
return versoCareggiataDoppio;
}
public void setVersoCareggiataDoppio(Set<GraphNodesRelationship> versoCareggiataDoppio) {
this.versoCareggiataDoppio = versoCareggiataDoppio;
}

public void addDiscordantRoadElementGraphRelation(GraphNode endNode, float lunghezzaArco, long elementoStrdaleDbId ){
//Invocando questo metodo indico come nodo iniziale sempre l'oggetto this attuale
GraphNodesRelationship relation = new GraphNodesRelationship(this, endNode, lunghezzaArco, elementoStrdaleDbId);
if( !versoCareggiataDiscorde.contains(relation) ){
versoCareggiataDiscorde.add(relation);
}
}
public void addConcordantRoadElementGraphRelation(GraphNode endNode, float lunghezzaArco, long elementoStrdaleDbId ){
//Invocando questo metodo indico come nodo iniziale sempre l'oggetto this attuale
GraphNodesRelationship relation = new GraphNodesRelationship(this, endNode, lunghezzaArco, elementoStrdaleDbId);
if( !versoCareggiataConcorde.contains(relation) ){
versoCareggiataConcorde.add(relation);
}
}
public void addTwoWayRoadElementGraphRelation(GraphNode endNode, float lunghezzaArco, long elementoStrdaleDbId ){
//Invocando questo metodo indico come nodo iniziale sempre l'oggetto this attuale
GraphNodesRelationship relation = new GraphNodesRelationship(this, endNode, lunghezzaArco, elementoStrdaleDbId);
if( !versoCareggiataDoppio.contains(relation) ){
versoCareggiataDoppio.add(relation);
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("ID giunzione: ");
sb.append(getGiunzioneDbId());
sb.append(". Coordinata X");
sb.append(getX());
sb.append(". Coordinata Y");
sb.append(getY());
sb.append(". Coordinata Z");
sb.append(getZ());
return sb.toString();
}
}


Then I wrote this relationship class:
Relationship class
@RelationshipEntity(type="ROAD_ELEMENT")
public class GraphNodesRelationship {
@GraphId
private Long relId;
//Id del record elemento stradale del DB
@Indexed(indexName="ELEMENTO_STRADALE_DB_ID", numeric=false, unique=true)
private String elementoStradaleDbId;
@StartNode
private GraphNode nodoIniziale;
@EndNode
private GraphNode nodoFinale;
//Peso dell'arco (lunghezza dell'elemento stradale)
private float lunghezzaArco;
public GraphNodesRelationship(GraphNode nodoIniziale, GraphNode nodoFinale, float lunghezzaArco, long elementoStradaleDbId){
setNodoIniziale(nodoIniziale);
setNodoFinale(nodoFinale);
setLunghezzaArco(lunghezzaArco);
setElementoStradaleDbId("elementoStradaleDbId_"+elementoStradaleDbId);
}
public GraphNodesRelationship(){
}
public GraphNode getNodoIniziale() {
return nodoIniziale;
}

public void setNodoIniziale(GraphNode nodoIniziale) {
Assert.notNull(nodoIniziale, "Impossibile creare la relazione; passato un nodoIniziale nullo"); 
this.nodoIniziale = nodoIniziale;
}

public GraphNode getNodoFinale() {
return nodoFinale;
}

public void setNodoFinale(GraphNode nodoFinale) {
Assert.notNull(nodoFinale, "Impossibile creare la relazione; passato un nodoFinale nullo");
this.nodoFinale = nodoFinale;
}

public float getLunghezzaArco() {
return lunghezzaArco;
}

public void setLunghezzaArco(float lunghezzaArco) {
this.lunghezzaArco = lunghezzaArco;
}
public String getElementoStradaleDbId() {
return elementoStradaleDbId;
}
public void setElementoStradaleDbId(String elementoStradaleDbId) {
this.elementoStradaleDbId = elementoStradaleDbId;
}
}


By using the listed classes, when I try to import data from my RDBMS to Neo4J I get the following exception:
org.springframework.dao.DataRetrievalFailureException: 0; nested exception is org.neo4j.graphdb.NotFoundException: 0
    at org.springframework.data.neo4j.support.Neo4jExceptionTranslator.translateExceptionIfPossible(Neo4jExceptionTranslator.java:63)
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:58)
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:163)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
    at com.sun.proxy.$Proxy25.save(Unknown Source)
    at it.eng.tz.pinf.graph.creator.service.impl.PinfDbSisGraphCreatorSvcImpl.creatGraph(PinfDbSisGraphCreatorSvcImpl.java:122)
    at it.eng.pinf.graph.extractor.test.PinfGraphTest.graphCreationTest(PinfGraphTest.java:72)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.neo4j.graphdb.NotFoundException: 0
    at org.neo4j.rest.graphdb.ExecutingRestAPI.getRelationshipById(ExecutingRestAPI.java:100)
    at org.neo4j.rest.graphdb.RestAPIFacade.getRelationshipById(RestAPIFacade.java:62)
    at org.neo4j.rest.graphdb.RestGraphDatabase.getRelationshipById(RestGraphDatabase.java:87)
    at org.springframework.data.neo4j.support.mapping.EntityStateHandler.getPersistentState(EntityStateHandler.java:110)
    at org.springframework.data.neo4j.support.mapping.EntityStateHandler.getPersistentState(EntityStateHandler.java:93)
    at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister.getPersistentState(Neo4jEntityPersister.java:221)
    at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister.persist(Neo4jEntityPersister.java:248)
    at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister.persist(Neo4jEntityPersister.java:231)
    at org.springframework.data.neo4j.support.Neo4jTemplate.save(Neo4jTemplate.java:294)
    at org.springframework.data.neo4j.fieldaccess.RelatedToViaCollectionFieldAccessorFactory$RelatedToViaCollectionFieldAccessor.persistEntities(RelatedToViaCollectionFieldAccessorFactory.java:99)
    at org.springframework.data.neo4j.fieldaccess.RelatedToViaCollectionFieldAccessorFactory$RelatedToViaCollectionFieldAccessor.setValue(RelatedToViaCollectionFieldAccessorFactory.java:93)
    at org.springframework.data.neo4j.fieldaccess.DefaultEntityState.setValue(DefaultEntityState.java:113)
    at org.springframework.data.neo4j.support.mapping.SourceStateTransmitter.setEntityStateValue(SourceStateTransmitter.java:70)
    at org.springframework.data.neo4j.support.mapping.SourceStateTransmitter.access$100(SourceStateTransmitter.java:40)
    at org.springframework.data.neo4j.support.mapping.SourceStateTransmitter$4.doWithAssociation(SourceStateTransmitter.java:113)
    at org.springframework.data.mapping.model.BasicPersistentEntity.doWithAssociations(BasicPersistentEntity.java:269)
    at org.springframework.data.neo4j.support.mapping.SourceStateTransmitter.copyPropertiesTo(SourceStateTransmitter.java:109)
    at org.springframework.data.neo4j.support.mapping.Neo4jEntityConverterImpl.write(Neo4jEntityConverterImpl.java:167)
    at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister$CachedConverter.write(Neo4jEntityPersister.java:179)
    at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister.persist(Neo4jEntityPersister.java:243)
    at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister.persist(Neo4jEntityPersister.java:231)
    at org.springframework.data.neo4j.support.Neo4jTemplate.save(Neo4jTemplate.java:294)
    at org.springframework.data.neo4j.support.Neo4jTemplate.save(Neo4jTemplate.java:288)
    at org.springframework.data.neo4j.repository.AbstractGraphRepository.save(AbstractGraphRepository.java:113)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:358)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:343)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
    ... 33 more

It's like if it tries to first load the Relationship and then to insert a new one....can this be related to the fact that I control if the set contains the relationship?
Moreover if I use different type of relationship, all works pretty good....do you have any suggestion about this behaviour?

thank you
Angelo
Reply all
Reply to author
Forward
0 new messages