Neo4j one-to-many fetch data

2019-07-19 01:53发布

In my Spring Boot/Neo4j application I have a following entities:

@NodeEntity
public class User extends BaseEntity {

    private static final String HAS = "HAS";

    @GraphId
    private Long id;

    private String username;

    private String password;

    private String email;

    private String firstName;

    private String lastName;

    @RelatedTo(type = HAS, direction = Direction.OUTGOING)
    private Set<Role> roles = new HashSet<Role>();

....

}


@NodeEntity
public class Vote extends BaseEntity {

    private static final String VOTED_ON = "VOTED_ON";
    private final static String VOTED_FOR = "VOTED_FOR";
    private static final String CREATED_BY = "CREATED_BY";

    @GraphId
    private Long id;

    @RelatedTo(type = VOTED_FOR, direction = Direction.OUTGOING)
    private Decision decision;

    @RelatedTo(type = VOTED_ON, direction = Direction.OUTGOING)
    private Criterion criteria;

    @RelatedTo(type = CREATED_BY, direction = Direction.OUTGOING)
    private User author;

    private double weight;

    private String description;


}

and I have a following SDN repository method:

@Query("MATCH (d:Decision)<-[:VOTED_FOR]-(v:Vote)-[:VOTED_ON]->(c:Criterion) WHERE id(d) = {decisionId} AND id(c) = {criterionId} RETURN v")
List<Vote> getVotes(@Param("decisionId") Long decisionId, @Param("criterionId") Long criterionId);

In the result I have a list of Vote.

On the client I'd like to display list of these votes with not only user(author) Id but and with author username also.

How to fetch based on the query above Vote.author.username and Vote.author.id and do not fetch all other information from User entity associated with Vote entity? Anyway, right now I only have Vote.author.id value.

EDITED:

following query

@Query("MATCH (d:Decision)<-[:VOTED_FOR]-(v:Vote)-[:VOTED_ON]->(c:Criterion) WHERE id(d) = {decisionId} AND id(c) = {criterionId} WITH v, d, c MATCH v-[:CREATED_BY]->(u:User) RETURN {id: v.id, weight: v.weight, description: v.description, `decision.id` : d.id, `criterion.id` : c.id, `author.id`: u.id, `author.username`: u.username} as v")
List<Vote> getVotesForDecisionOnCriterion(@Param("decisionId") Long decisionId, @Param("criterionId") Long criterionId);

doesn't work with a following exception:

org.springframework.dao.InvalidDataAccessApiUsageException: [Assertion failed] - entity is required; it must not be null
    at org.springframework.data.neo4j.support.ParameterCheck.notNull(ParameterCheck.java:29)
    at org.springframework.data.neo4j.support.Neo4jTemplate.projectTo(Neo4jTemplate.java:240)
    at org.springframework.data.neo4j.support.conversion.EntityResultConverter.doConvert(EntityResultConverter.java:73)
    at org.springframework.data.neo4j.conversion.DefaultConverter.convert(DefaultConverter.java:44)
    at org.springframework.data.neo4j.support.conversion.EntityResultConverter.convert(EntityResultConverter.java:165)
    at org.springframework.data.neo4j.conversion.QueryResultBuilder$1.underlyingObjectToObject(QueryResultBuilder.java:86)

2条回答
甜甜的少女心
2楼-- · 2019-07-19 02:21

I can't help with the spring but does this cypher get you what you want?

MATCH (d:Decision)<-[:VOTED_FOR]-(v:Vote)-[:VOTED_ON]->(c:Criterion)
WHERE id(d) = {decisionId} 
  AND id(c) = {criterionId} 
WITH v
MATCH v-[:CREATED_BY]->(u:User)
RETURN {id: v.id
       , weight: v.weight
       , `author.id`: u.id
       , `author.username`: u.username
       ... } as v
查看更多
孤傲高冷的网名
3楼-- · 2019-07-19 02:26

Try this with a DTO (can also be an interface with getters):

@QueryResult
class VoteView {
   String id;
   Double weight;
   String description;
   String decisionId;  
   String criterionId;  
   String authorId;
   String authorName;
}

@Query("MATCH (d:Decision)<-[:VOTED_FOR]-(v:Vote)-[:VOTED_ON]->(c:Criterion) WHERE id(d) = {decisionId} AND id(c) = {criterionId} WITH v, d, c MATCH v-[:CREATED_BY]->(u:User) RETURN {id: v.id, weight: v.weight, description: v.description, decisionId : d.id, criterionId : c.id, authorId: u.id, authorName: u.username} as v")
List<VoteView> getVotesForDecisionOnCriterion(@Param("decisionId") Long decisionId, @Param("criterionId") Long criterionId);
查看更多
登录 后发表回答