Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
03-20-2021 12:10 AM
Hi, I'm new to Neo4j! I'm currently working on a simple REST API but I cannot seem to figure out how to return both nodes and relations in a single endpoint.
My design is super simple. I have a bunch of different resource nodes [CLIENT, SERVER, DB] (which all inherit from RESOURCE) and a PROJECT node that connects them. The resource nodes have connections between them and every resource connects to exactly one Project. An example from the Neo4j Browser is attached (this is my entire DB right now - and is exactly what I want to return on my endpoint😞
Now, I'm trying to return "everything" (nodes and relationships) for everything connected to a specific Project (right now I'm doing all projects by I would filter by Project ID). Since I want to return different type nodes and relations I created a ProjectsDTO as my projection class (since @QueryResult is not SDN6).
@Value
public class ProjectsDTO {
private ProjectEntity project;
private ResourceEntity resource;
private ResourceOfRelationshipEntity relation;
}
@Repository
public interface ProjectRepo extends Neo4jRepository<ProjectEntity, String> {
@Query("MATCH (n)-[r:RESOURCE_OF]->(m:ProjectEntity) return n as resource, r as relation, m as project")
Collection<ProjectsDTO> getAllProjects();
}
I know my query works because this is what I get on the browser (not sure why "relation" is {}):
However, making the query on the repo is not working - I am either getting all fields as null or the following error:
Could not find mappable nodes or relationships inside node<10> for org.springframework.data.neo4j.core.mapping.DefaultNeo4jPersistentEntity@51310725
org.springframework.data.neo4j.core.mapping.NoRootNodeMappingException: Could not find mappable nodes or relationships inside node<10> for org.springframework.data.neo4j.core.mapping.DefaultNeo4jPersistentEntity@51310725
I have also added the key parts of my entities in case it's useful.
public abstract class ResourceEntity {
....
@Relationship(type = "CONNECTS", direction = Relationship.Direction.OUTGOING)
private List<ConnectsRelationshipEntity> resources;
....
}
@Node
public class ProjectEntity {
...
@Relationship(type = "RESOURCE_OF", direction = Relationship.Direction.INCOMING)
private List<ResourceOfRelationshipEntity> resources;
...
}
@RelationshipProperties
public class ConnectsRelationshipEntity {
@Id @GeneratedValue
private Long relationshipId;
@Property
private int latency;
@TargetNode
private ResourceEntity targetResource;
public ConnectsRelationshipEntity(int latency, ResourceEntity targetResource) {
this.latency = latency;
this.targetResource = targetResource;
}
}
@RelationshipProperties
public class ResourceOfRelationshipEntity {
@Id @GeneratedValue
private Long relationshipId;
@TargetNode
private ResourceEntity resource;
public ResourceOfRelationshipEntity(ResourceEntity resource) {
this.resource = resource;
}
}
Not sure if I'm missing something or my approach is wrong. Would love any help!
03-25-2021 07:34 AM
There are several bits in there that we should talk about.
What you are trying to define is not a Project
projection but something different.
A projection defines a (reduced) view on an entity. This would mean that you can define the properties and relationships of the ProjectEntity
in there but not pull those ones to the first level of the object graph.
Since you are already using a DTO projection (in opposite to an interface projection) you could of course create methods to access the nested attributes and mimic a top-level existence.
If this is not needed, I would always advise you to use interface based projection.
Some more information about projections: Spring Data Neo4j
Secondly, your query does not what it is supposed to do. Because you were mentioning @QueryResult
before I assume that you have used it with Neo4j-OGM.
Neo4j-OGM collects all returned data before the mapping process starts. It is ok with getting bite-size information that eventually forms a complete instance of an entity. SDN 6 does not support this because this would mean that it cannot support the reactive flow, for example.
Every record in the returned result has to define the complete entity.
Looking at your query, this should be something like
MATCH (n:Resource)-[r:RESOURCE_OF]->(m:ProjectEntity) return collect(n) as resource, collect(r) as relation, m as project
This would return project-focused records because the relationships and related nodes are getting returned along with the Project
node.
All the sessions of the conference are now available online