Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
The Spring Data for neo4j @Query annotation does not populate any child/parent Nodes marked by the @Relationship annotation.
When using the standard @CrudRepository or @PagingAndSortingRepository queries in a SpringData Repository class, the Child/Parent Nodes classes are returned fulled populated.
Repository Interface
@Repository("trackerRepository")
public interface TrackerRepository extends PagingAndSortingRepository<Tracker, String> {
Tracker findByTrackerId(@NotNull String trackerId);
Node Class
public final class Tracker extends Node {
@NotNull
@JsonProperty("trackerId")
private String trackerId;
@NotNull
@Relationship(type = "ASSIGNED_TO")
@JsonProperty("asset")
private Asset asset;
@NotNull
@Relationship(type = "ISSUED_BY")
@JsonProperty("organization")
private Organization organization;
When using the findByTrackerId method, the query generated by Spring using the method name/signature works perfectly and returns the fully populated Asset and Organization nodes.
However, when using the @Query annotation and not the Spring queries generated from the method signature, the @Relationship nodes are not returned with the query response.
Repository Interface
@Repository("trackerRepository")
public interface TrackerRepository extends PagingAndSortingRepository<Tracker, String> {
@Query("MATCH (tracker:Tracker) WHERE (tracker.trackerId = $trackerId) RETURN tracker")
Tracker findByTrackerId(@NotNull @Param("trackerId") String trackerId);
Is it possible to configure repository methods marked with @Query to join parent/child Nodes defined by the @Relationship annotation?
When writing a custom query with @Query you need to specify exactly what you're bringing back:
@Relationship(type = "ASSIGNED_TO")
@JsonProperty("asset")
private Asset asset;
@NotNull
@Relationship(type = "ISSUED_BY")
@JsonProperty("organization")
private Organization organization;
Alternatively (I'm assuming this is SDN 6 with Spring Data as opposed to SDN 5 and OGM?) you can just drop the custom query and use the out-of-the-box SPEL of findByTrackerId
and the repository methods will create a automagical Cypher query that gets seamlessly serialized by the @Repository methods.
In general custom @Query is useful when needing to write more efficient queries then those offered by the SDN sugars.
But to answer your question more directly this should work:
@Query("MATCH (tracker:Tracker {trackerId: $trackerId})
WITH tracker
OPTIONAL MATCH (tracker)-[r_issued_by:ISSUED_BY]->(organization:Organization)
WITH tracker, COLLECT(r_issued_by) AS organization_rels, COLLECT(DISTINCT organization) AS organizations
OPTIONAL MATCH (tracker)-[r_assigned_to:ASSIGNED_TO]->(asset:Asset)
RETURN tracker, organization_rels, organizations, COLLECT(r_assigned_to) AS asset_rels, COLLECT(DISTINCT asset) AS assets;")
Looking at your annotations it looks like both ISSUED_BY
and ASSIGNED_TO
are outgoing relationships from :Tracker
?
the collects are because of this:
https://community.neo4j.com/t/sdn-rx-dynamic-relationships-not-being-populated-with-custom-query/24456
–
@false_memories has it right, but the WITH
clause isn't necessary in this case. If you're just using variables from the match clause, you don't need a WITH
. You need a WITH
only if you're manipulating the variables in some way:
https://neo4j.com/docs/cypher-manual/current/clauses/with/#with-filter-on-aggregate-function-results
In addition, looks like your relationships are required from your @NotNull
annotations, so you should drop the OPTIONAL
So a slightly better query is:
@Query("MATCH (tracker:Tracker {trackerId: $trackerId})
MATCH (tracker)-[r_issued_by:ISSUED_BY]->(organization:Organization)
MATCH (tracker)-[r_assigned_to:ASSIGNED_TO]->(asset:Asset)
RETURN tracker,
COLLECT(r_issued_by), COLLECT(organization) AS organization,
COLLECT(r_assigned_to), COLLECT(asset) AS asset")
I like to match the as
clause to my actual relationship names because it makes it appear a little cleaner when looking at raw results.
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.