Reputation: 3281
I am working on a Spring Boot application using Neo4j as the database. I have a UserEntity
class that has a relationship with UserContactEntity
.
However, when I run a query to fetch UserEntity
along with its contacts
(depth=2), the contacts
field is always null.
Here are the relevant parts of my code:
UserEntity.kt:
import org.neo4j.ogm.annotation.*
import org.springframework.data.neo4j.annotation.Depth
import org.springframework.data.neo4j.annotation.Query
import org.springframework.data.neo4j.repository.Neo4jRepository
import org.springframework.data.repository.query.Param
...
@NodeEntity("User")
class UserEntity : PermissionableEntity, Serializable {
@Id
@Property("userId")
var userId: StringID? = null
@Relationship("PERSON_HAS_CONTACT")
var contacts: MutableSet<UserContactEntity> = mutableSetOf()
// Other fields and methods...
}
UserContactEntity.kt:
import org.neo4j.ogm.annotation.Id
import org.neo4j.ogm.annotation.NodeEntity
import org.neo4j.ogm.annotation.Property
import org.springframework.data.neo4j.annotation.Query
import org.springframework.data.neo4j.repository.Neo4jRepository
import org.springframework.data.repository.query.Param
...
@NodeEntity("UserContact")
class UserContactEntity : Serializable {
// Fields and methods...
}
UserRepository.kt:
interface UserRepository : Neo4jRepository<UserEntity, StringID> {
fun findByUserIdIn(userIds: Collection<StringID>, @Depth depth: Int = 2): Iterable<UserEntity>
}
I have confirmed that contact data exists, and is correctly associated with the user, by running this query in the Neo4j browser:
MATCH (u:User)-[r:PERSON_HAS_CONTACT]->(c:UserContact)
RETURN u.userId AS userId, c.id AS contactId, c.type AS contactType, c.detail AS contactDetail, c.verified AS contactVerified
I believe I have identified the issue in the logs which show that the generated query uses the wrong relationship mappings. It uses CONTACTS
instead of PERSON_HAS_CONTACT
and also maps some other relationships that aren't defined in UserEntity
.
[.0-8080-exec-10] o.s.d.n.r.query.PartTreeNeo4jQuery : Executing query for method findByUserIdIn
[.0-8080-exec-10] o.n.o.drivers.bolt.request.BoltRequest : Request: MATCH (n:`User`) WHERE n.`userId` IN $`userId_0` WITH n RETURN n,[ [ (n)-[r_m1:`MEMBER_FIELDS`]-(f1:`FieldValue`) | [ r_m1, f1, [ [ (f1)-[r_d2:`DEFINITION`]-(f2:`FieldDefinition`) | [ r_d2, f2 ] ] ] ] ], [ (n)-[r_c1:`CONTACTS`]-(u1:`UserContact`) | [ r_c1, u1 ] ] ], ID(n) with params {userId_0=[b3c98b44f2e005250b23a4b02938e9f6, fd587ab3096750e10e5c9a0de61c12bb]}
I have created a custom query that has solved the issue, and I am using as a workaround for now.
@Query("MATCH (u:User)-[:PERSON_HAS_CONTACT]->(c:UserContact)WHERE u.userId IN \$userIds WITH u, collect(c) AS contacts RETURN u, [ [ (u)-[r:`PERSON_HAS_CONTACT`]->(c) | [ r, c ] ] ], ID(u)")
fun findByUserIdInWithContacts(@Param("userIds") userIds: Collection<StringID>): Iterable<UserEntity>
I am still concerned that the default query repository method does not work and that it uses relationships that seem to be coming from somewhere else.
I cannot find a relationship CONTACTS
or MEMBER_FIELDS
defined in my codebase or in the database.
MATCH (u:User)-[r]->(n)
RETURN type(r) AS relationshipType, count(r) AS count, labels(n) AS targetLabels
ORDER BY count DESC
Returns
relationshipType count targetLabels
"USER_HAS_ROLES" 11 ["SystemRole"]
"USER_HAS_CREDENTIALS" 5 ["Credentials"]
"PERSON_HAS_CONTACT" 5 ["UserContact"]
"MARKER_HAS_CREDIBILITY" 1 ["ActiveCompetition"]
I checked the Spring Data Neo4j documentation and didn't find any other way to define relationships.
I have cleaned my local repository and the build to ensure that there is no dead or old code floating around somewhere.
rm -rf ~/.m2/repository/org/my/app
./gradlew clean bootRun | tee output.log
I have a similar entity for Organisation and it is able to load its relationships when using the default queries, so this is something specific to this user entity.
My questions:
Versions:
Upvotes: 0
Views: 82