Skip to content

Resolve field alias in Cypher only if no DataFetchingInterceptor is used #270

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .run/Run All tests including integration tests.run.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run All tests including integration tests" type="JUnit" factoryName="JUnit">
<module name="neo4j-graphql-java (1)" />
<module name="neo4j-graphql-java"/>
<option name="PACKAGE_NAME" value="org.neo4j.graphql" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
Expand All @@ -13,4 +13,4 @@
<option name="Make" enabled="true" />
</method>
</configuration>
</component>
</component>
12 changes: 11 additions & 1 deletion core/src/main/kotlin/org/neo4j/graphql/SchemaBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ class SchemaBuilder(

val builder = RuntimeWiring.newRuntimeWiring()
val codeRegistryBuilder = GraphQLCodeRegistry.newCodeRegistry()

val schemaBuilder = SchemaBuilder(typeDefinitionRegistry, config)
schemaBuilder.augmentTypes()
schemaBuilder.registerScalars(builder)
Expand Down Expand Up @@ -196,6 +195,9 @@ class SchemaBuilder(
dataFetchingInterceptor: DataFetchingInterceptor?,
typeDefinitionRegistry: TypeDefinitionRegistry = this.typeDefinitionRegistry
) {
if (dataFetchingInterceptor != null) {
codeRegistryBuilder.defaultDataFetcher { AliasPropertyDataFetcher() }
}
addDataFetcher(typeDefinitionRegistry.queryTypeName(), OperationType.QUERY, dataFetchingInterceptor, codeRegistryBuilder)
addDataFetcher(typeDefinitionRegistry.mutationTypeName(), OperationType.MUTATION, dataFetchingInterceptor, codeRegistryBuilder)
}
Expand Down Expand Up @@ -275,4 +277,12 @@ class SchemaBuilder(
typeDefinitionRegistry.add(inputType)
return inputName
}

class AliasPropertyDataFetcher : DataFetcher<Any> {
override fun get(env: DataFetchingEnvironment): Any? {
val source = env.getSource<Any>() ?: return null
val propertyName = env.mergedField.singleField.alias ?: env.mergedField.singleField.name
return PropertyDataFetcherHelper.getPropertyValue(propertyName, source, env.fieldType, env)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
:toc:

= Field aliasing does not work if using DataFetchingInterceptor

== Issue

https://github.com/neo4j-graphql/neo4j-graphql-java/issues/267

== Schema

[source,graphql,schema=true]
----
type Movie {
query: Int @cypher(statement: "RETURN 42", passThrough:true)
title: String
actors: [Actor!] @relation(name: "ACTED_IN", direction:IN)
}
type Actor {
name: String
}
----

.Test-Data
[source,cypher,test-data=true]
----
CREATE (m:Movie{ title: 'movie 1' }),
(max:Actor{ name: 'Max' }),
(marie:Actor{ name: 'Marie' }),
(max)-[:ACTED_IN]->(m),
(marie)-[:ACTED_IN]->(m);
----

== Queries

.GraphQL-Query
[source,graphql]
----
query {
movieAlias: movie {
title
title1: title
title2: title
query
number1: query
number2: query
actors(orderBy: [ name_asc ]) { name }
allMax: actors(filter: { name: "Max" }) { name }
allMarie: actors(filter: { name: "Marie" }) { name }
}
}
----

.GraphQL-Response
[source,json,response=true]
----
{
"movieAlias" : [ {
"title" : "movie 1",
"title1" : "movie 1",
"title2" : "movie 1",
"query" : 42,
"number1" : 42,
"number2" : 42,
"actors" : [ {
"name" : "Marie"
}, {
"name" : "Max"
} ],
"allMax" : [ {
"name" : "Max"
} ],
"allMarie" : [ {
"name" : "Marie"
} ]
} ]
}
----

.Cypher Params
[source,json]
----
{
"filterMovieAliasAllMarieName" : "Marie",
"filterMovieAliasAllMaxName" : "Max"
}
----

.Cypher
[source,cypher]
----
MATCH (movieAlias:Movie)
CALL {
WITH movieAlias
WITH movieAlias AS this
RETURN 42 AS movieAliasQuery LIMIT 1
}
CALL {
WITH movieAlias
WITH movieAlias AS this
RETURN 42 AS movieAliasNumber1 LIMIT 1
}
CALL {
WITH movieAlias
WITH movieAlias AS this
RETURN 42 AS movieAliasNumber2 LIMIT 1
}
CALL {
WITH movieAlias
MATCH (movieAlias)<-[:ACTED_IN]-(movieAliasActors:Actor)
WITH movieAliasActors ORDER BY movieAliasActors.name ASC
RETURN collect(movieAliasActors {
.name
}) AS movieAliasActors
}
CALL {
WITH movieAlias
MATCH (movieAlias)<-[:ACTED_IN]-(movieAliasAllMax:Actor)
WHERE movieAliasAllMax.name = $filterMovieAliasAllMaxName
RETURN collect(movieAliasAllMax {
.name
}) AS movieAliasAllMax
}
CALL {
WITH movieAlias
MATCH (movieAlias)<-[:ACTED_IN]-(movieAliasAllMarie:Actor)
WHERE movieAliasAllMarie.name = $filterMovieAliasAllMarieName
RETURN collect(movieAliasAllMarie {
.name
}) AS movieAliasAllMarie
}
RETURN movieAlias {
.title,
title1: movieAlias.title,
title2: movieAlias.title,
query: movieAliasQuery,
number1: movieAliasNumber1,
number2: movieAliasNumber2,
actors: movieAliasActors,
allMax: movieAliasAllMax,
allMarie: movieAliasAllMarie
} AS movieAlias
----

'''