Relationships not returned in query

**I posted this in the wrong category at first, my apologies, cross post: How to get connected in Java **

I'm trying to model the electricity net, the data is structured in this way:

ElektraNodes (Label) (has objectId):

  • Transformer (Label)
  • Station (Label)
  • Etc.

ElektraLinks (Label) (has objectId and length and connections)

  • Cable (Label)
  • Rail (Label)
  • Field (Label)
  • Etc.

So for example a rail would be represented as:

{
  "identity": 142244, 
  "labels": [
    "ELink",
    "rail",
  ],
  "properties": {
"length": "15.5",
"objectId": "114999",

  }
}

This gives me working queries in the Neo4J browser, for example:

MATCH (n:rail {objectId: "114999"}) 
 CALL apoc.path.spanningTree(n, 
 {labelFilter: "/station", 
 minLevel: 1, 
 maxLevel: 100})
 YIELD path 
 WITH n, nodes(path) as node
 RETURN n, node

The above would give me the starting node with ID 114999 and all nodes returns from the path that the spanningTree gives me. Up until here that's perfect.

But now I want to return all nodes, which can be both ElektraNodes and all its subtypes, and ElektraLinks and all its subtypes, in Java.

For example I create a repository that has this:

@Repository
public interface NodeLinkRepository extends ReactiveNeo4jRepository<ELinkEntity, String> {

    @Query("MATCH (n {objectId: \"114999\"}) \n" +
            " CALL apoc.path.spanningTree(n, \n" +
            " {labelFilter: \"/station\", \n" +
            " minLevel: 1, \n" +
            " maxLevel: 100})\n" +
            " YIELD path \n" +
            " WITH n, nodes(path) as node\n" +
            " RETURN n, node")
    Flux<ELinkEntity > findPath();

Where the ELinkEntity is:

@Node("ELink")
@Data // generates setters and getters
public class ELinkEntity {

    @Id
    private String objectId;    

    @Relationship(type = "CONNECTED", direction = Outgoing)
    private Set<ENodeEntity> connected = new HashSet<>();

    private String length;
}

and I do the same for my nodes:

@Node("ENode")
@Data
public class ENodeEntity{

    @Id
    private String objectId;    
}

If I would run the above query, instead of giving me the entire path which would consist of a 100 or so objects, I only get the first object node:

[
{
"objectId": "114999",
"connected": [],
"lengte": "15.5"
},
{
"objectId": "114999",
"connected": [],
"lengte": "15.5"
}
]

So as you can see, the links and followings nodes are not part of the response, while in NEO4j browser, this returns all nodes and all links, the full path. What do I need to do in java to return the full content of the nodes?

Then for the next step, what would be the proper way to introduce the inheritance stack that I have?

Looks like not even simple queries are filling relationships:

@Query("MATCH (n:ELink)<-[c:CONNECTED]-(m:ENode)-[e:CONNECTED]->(o:ELink) where n.objectId=$objectId RETURN n,collect(c),collect(m),collect(e),collect(o)")
Flux<ELink> findNearest(String objectId);

While debugging I can see that the query does actually find the relationships, they're just not being filled. The data relationship is being created in this way:

CALL apoc.load.jdbc('jdbc:oracle:thin:@','SELECT * FROM TABLE',[],{credentials:{user:, password: }}) YIELD row
MATCH (node:ENode {objectId:row.OBJECT1_ID}),(link:ELink {objectId:row.OBJECT2_ID})
CREATE (node)-[:CONNECTED]->(link)

Which seems to work as far as the queries are concerned.

Since you are returning only nodes you are not getting relationships returned. If you return path you will get all the data.

Thanks anthapu! Now running into the following error:

2020-09-21 08:29:57.318  WARN 4064 --- [o4jDriverIO-2-2] o.n.s.d.c.mapping.DefaultNeo4jConverter  : Could not find mappable nodes or relationships inside Record<{node: [node<345271>, node<2378176>, node<1092384>], relations: [relationship<3445159>, relationship<3445680>]}> for org.neo4j.springframework.data.core.mapping.DefaultNeo4jPersistentEntity@25ad4f71
2020-09-21 08:29:57.484  WARN 4064 --- [o4jDriverIO-2-2] .r.s.Neo4jPersistenceExceptionTranslator : Don't know how to translate exception of type class java.lang.IllegalStateException

Which is strange, does that ring any bell?

How do you return the relationships now?
Also the stacktrace of the first exception would be helpful. I assume that SDN cannot find the right relationships for the nodes.
I will take at least your

MATCH (n:ELink)<-[c:CONNECTED]-(m:ENode)-[e:CONNECTED]->(o:ELink) where n.objectId=$objectId RETURN n,collect(c),collect(m),collect(e),collect(o)

example with me to look into this.

Hi Gerrit, thanks for joining in!

The complete stacktrace is:

java.lang.IllegalStateException: Mapping function org.neo4j.springframework.data.core.schema.Schema$$Lambda$945/0x0000000801022040@558d4146 returned illegal null value for record Record<{node: [node<345271>, node<2378176>, node<1092384>], relations: [relationship<3445159>, relationship<3445680>]}>
	at org.neo4j.springframework.data.core.DelegatingMappingFunctionWithNullCheck.apply(DelegatingMappingFunctionWithNullCheck.java:50) ~[spring-data-neo4j-rx-1.1.1.jar:1.1.1]
	Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
	|_ checkpoint ? Handler com.alliander.gpsapineo4jpoc.controller.ElektraController#getPath() [DispatcherHandler]
	|_ checkpoint ? HTTP GET "/elektra/path" [ExceptionHandlingWebHandler]
Stack trace:
		at org.neo4j.springframework.data.core.DelegatingMappingFunctionWithNullCheck.apply(DelegatingMappingFunctionWithNullCheck.java:50) ~[spring-data-neo4j-rx-1.1.1.jar:1.1.1]
		at org.neo4j.springframework.data.core.DelegatingMappingFunctionWithNullCheck.apply(DelegatingMappingFunctionWithNullCheck.java:38) ~[spring-data-neo4j-rx-1.1.1.jar:1.1.1]
		at org.neo4j.springframework.data.core.DefaultReactiveNeo4jClient$DefaultRecordFetchSpec.lambda$executeWith$2(DefaultReactiveNeo4jClient.java:243) ~[spring-data-neo4j-rx-1.1.1.jar:1.1.1]
		at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:100) ~[reactor-core-3.3.9.RELEASE.jar:3.3.9.RELEASE]
		at org.neo4j.driver.internal.shaded.reactor.core.publisher.StrictSubscriber.onNext(StrictSubscriber.java:89) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.reactor.core.publisher.FluxCreate$IgnoreSink.next(FluxCreate.java:618) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.reactor.core.publisher.FluxCreate$SerializedSink.next(FluxCreate.java:153) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.reactive.InternalRxResult.lambda$createRecordConsumer$3(InternalRxResult.java:95) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.handlers.pulln.BasicPullResponseHandler.handleRecord(BasicPullResponseHandler.java:134) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.handlers.pulln.BasicPullResponseHandler$State$2.onRecord(BasicPullResponseHandler.java:308) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.handlers.pulln.BasicPullResponseHandler.onRecord(BasicPullResponseHandler.java:89) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.async.inbound.InboundMessageDispatcher.handleRecordMessage(InboundMessageDispatcher.java:97) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.messaging.v1.MessageReaderV1.unpackRecordMessage(MessageReaderV1.java:94) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.messaging.v1.MessageReaderV1.read(MessageReaderV1.java:65) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.async.inbound.InboundMessageHandler.channelRead0(InboundMessageHandler.java:83) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.async.inbound.InboundMessageHandler.channelRead0(InboundMessageHandler.java:35) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:355) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:321) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:295) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.async.inbound.MessageDecoder.channelRead(MessageDecoder.java:47) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:355) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:321) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:308) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:422) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:355) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:714) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:650) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:576) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at org.neo4j.driver.internal.shaded.io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[neo4j-java-driver-4.0.1.jar:4.0.1-979f102fbfd27e6393f672da8c7d59f6fabbbe0e]
		at java.base/java.lang.Thread.run(Thread.java:832) ~[na:na]

Currently I have the following:

@Query("MATCH (n {objectId: \"114999\"}) \n" +
            " CALL apoc.path.spanningTree(n, \n" +
            " minLevel: 1, \n" +
            " maxLevel: 100})\n" +
            " YIELD path \n" +
            " WITH nodes(path) as node, relationships(path) as relations\n" +
            " RETURN node, relations")
    Flux<ELinkEntity> findPath();

Concerning your last question, do you mean that you need example data?

The current DTO's are:

@Node("ELink")
@Data
public class ELinkEntity {

    @Id
    @GeneratedValue
    private final Long Id;

    private final String objectId;

    @Relationship(type = "CONNECTED", direction = INCOMING)
    private Set<ENodeEntity> connected = new HashSet<>();

    private final String lengte;
}

@Node("ENode")
@Data
public class ENodeEntity {

    @Id
    @GeneratedValue
    private final Long Id;

    private final String objectId;
}

@gerrit.meier

there is definitely something wrong in the mapper (other than the error being thrown). For me it looks like it has trouble with returning paths, a list of nodes with a list of relations. When I call the functions directly on the driver I get a proper result:

 public Flux<ELinkEntity> getPathClient(){
        return this.client
                .query("MATCH (n {objectId: \"114999\"})" +
                        " CALL apoc.path.spanningTree(n," +
                        " {labelFilter: \"/ms_veld_ligging\"," +
                        " minLevel: 1, " +
                        " maxLevel: 100})" +
                        " YIELD path " +
                        " WITH nodes(path) as node, relationships(path) as relations" +
                        " RETURN node")
                .in("neo4j")
                .fetchAs(ELinkEntity.class)
                .mappedBy((TypeSystem t, Record record) -> {
                    return mapper(record)
                })
                .all();
    }

Yes I would need to do the mapping myself, but I get all the records and all the relations with all the proper types. I prefer not to do this though - shouldn't this be an out of the box solution?

To give you a sign of life:
I have now a pull request open that could solve you problem. It is primarily focused on our own generated queries, but if the returned data matches the format of the generated queries, this might work.
Basically you would do a return n, path in the end but I need to verify and/or broaden this functionality for custom queries.
Just as a side note:
For a correct mapping from custom queries results SDN assumes something like return n, collect(relationships), collect(targetNodes), so for one returned record you would have one (root) domain entity with all its relationships and related nodes.