Search code examples
cypherspring-data-neo4jspring-data-neo4j-4

Analogue of @Formula annotation from JPA for Spring data neo4j?


I'd like to calculate some properties of my domain objects at DB level using neo4j and return the read-only results. In JPA one can achieve this via @Formula annotation over field of domain object entity:

@Formula("(select avg(f.rating) from Feedback f where f.offer_id = offer_id)")
private Double rating;

What should one do to achieve the same behavior in Spring data neo4j? I wrote a Cypher query, but don't know where to use it.


Solution

  • A similar outcome can be achieved using @QueryResult

    • Create a class with fields to hold return data.
    • Annotate it with @QueryResult

    Example: (in Kotlin, which is what I had on hand)

    @QueryResult
    open class Principal constructor(applicationToken: String,
                                 profileId: String,
                                 stageName: String,
                                 showMeLaterDays: Float,
                                 roles: Array<Role>)
    {
    
        var applicationToken: String
        var profileId: String
        var stageName: String
        var showMeLaterDays: Float
    
        @Convert(RoleArrayAttributeConverter::class)
        var roles: Array<Role>
    
    
    
        init
        {
            this.applicationToken = applicationToken
            this.profileId = profileId
            this.stageName = stageName
            this.showMeLaterDays = showMeLaterDays
            this.roles = roles
        }
    
        //Provide a default constructor for OGM
        constructor() : this(applicationToken = "", profileId = "", stageName = "", showMeLaterDays = 0f,
            roles = emptyArray())
    }
    

    Then use it with a repository as follows:

    @Query("MATCH (n:CandidateProfile {applicationToken: {0} }) 
        RETURN n.id as profileId, n.applicationToken as applicationToken, n.stageName as stageName, n.showMeLaterDays as showMeLaterDays, n.roles as roles;")
    fun findByApplicationToken(token: String): Principal?
    
    • Note the way that node properties are returned to correspond with the class field names.
    • The same can be done with function results.