spring-data-neo4j
spring-data-neo4j copied to clipboard
Cannot retrieve Boolean value from Relationship in a SDN query projection
Setup
So I've got the following structure
- I've got Products that link to a Group
- the (directed) relation has properties (for actual values check the very bottom)
I'm using the following Spring Data repository query
@Repository
interface GroupRepository: ReactiveNeo4jRepository<Group, String> {
@Query("MATCH (product:Product) -[r:HAS_GROUP]-> (group:Group)" +
" WHERE group.id = \$groupId" +
" RETURN p AS product, properties(r)")
fun findProducts(groupId: String): Flux<ProductToGroupProjectionDTO>
}
and this is the DTO class
data class ProductToGroupProjectionDTO(
var product: Product? = null,
var enabled: Boolean? = null,
var options: Map<String, String?> = emptyMap(),
)
The issue
The repository query works and returns the correct number of projections.
But the resulting DTO only has the properties product and options set, enabled is null.
So if we look at the projection
RETURN product, properties(r)
What also does not work to the same effect
RETURN product, r{.*}
Workaround
But what somehow does work is either
RETURN product, properties(r), r.triable AS triable
or
RETURN product, r{.*}, r.triable AS triable
Question now is, why does SDN not automatically map a primitive (nullable) type (=Boolean) to the returned value?
Details
Technical stuff
- Spring Boot:
3.0.1 - Spring Data Neo4J:
7.0.0 - Neo4J Image:
neo4j:5.5.0-community
Here is the above mentioned and shown node structure, queried via
MATCH (product:Product)-[relation]->(group:Group)
RETURN product, relation, group
In text
╒════════════════════════════════════════════════════════════════╤═════════════════════════════════════╤═══════════════════════════════════════════════════════════╕
│"product" │"relation" │"group" │
╞════════════════════════════════════════════════════════════════╪═════════════════════════════════════╪════════════════════════════════════════════════════════════╡
│{"name":"Product 1","id":"50862361-8ae4-4c53-a2d7-f4719e5ebd98"}│{"options.foo":"bar","enabled":false}│{"name":"Group","id":"7c3e7a74-c989-4cb1-b44f-06b02ed01e57"}│
├────────────────────────────────────────────────────────────────┼─────────────────────────────────────┼────────────────────────────────────────────────────────────┤
│{"name":"Product 2","id":"6990700b-6818-4b4c-af8a-3e3c9ca6a132"}│{"options.foo":"bar","enabled":true} │{"name":"Group","id":"7c3e7a74-c989-4cb1-b44f-06b02ed01e57"}│
└────────────────────────────────────────────────────────────────┴─────────────────────────────────────┴────────────────────────────────────────────────────────────┘
In JSON
[
{
"product": {
"identity": 4,
"labels": [
"Product"
],
"properties": {
"name": "Product 1",
"id": "50862361-8ae4-4c53-a2d7-f4719e5ebd98"
},
"elementId": "4"
},
"relation": {
"identity": 3,
"start": 4,
"end": 6,
"type": "HAS_GROUP",
"properties": {
"options.foo": "bar",
"enabled": false
},
"elementId": "3",
"startNodeElementId": "4",
"endNodeElementId": "6"
},
"group": {
"identity": 6,
"labels": [
"Group"
],
"properties": {
"name": "Group",
"id": "7c3e7a74-c989-4cb1-b44f-06b02ed01e57"
},
"elementId": "6"
}
},
{
"product": {
"identity": 5,
"labels": [
"Product"
],
"properties": {
"name": "Product 2",
"id": "6990700b-6818-4b4c-af8a-3e3c9ca6a132"
},
"elementId": "5"
},
"relation": {
"identity": 4,
"start": 5,
"end": 6,
"type": "HAS_GROUP",
"properties": {
"options.foo": "bar",
"enabled": true
},
"elementId": "4",
"startNodeElementId": "5",
"endNodeElementId": "6"
},
"group": {
"identity": 6,
"labels": [
"Group"
],
"properties": {
"name": "Group",
"id": "7c3e7a74-c989-4cb1-b44f-06b02ed01e57"
},
"elementId": "6"
}
}
]
Spring Data Neo4j supports projections for entity-based projections. What you are trying to achieve is a mixture of an entity and additional information.
For those use cases I recommend to use the Neo4jClient with the custom query and make use of the entity aware mapping: https://docs.spring.io/spring-data/neo4j/reference/appendix/neo4j-client.html#neo4j-client.result-objects.mapping-functions.
With this you have to manually aggregate the parts mapped entity and custom property but you get more control over what happens. The Neo4jClient is Spring transaction aware. You can still use it in combination with other repository or Neo4jTemplate calls within the same unit of work.
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.