Skip to content

Commit 268a40d

Browse files
authored
Augment filter argument for nested fields (#208)
If the field of GraphQL Type maps to an *..n relation (a list) and there is currently no `filter`-argument defined, we now generate it in the augmented schema. The logic for handling these nested filters is already implementd, so no further code-adjustments are required. resolves #129
1 parent fc52604 commit 268a40d

File tree

3 files changed

+23
-16
lines changed

3 files changed

+23
-16
lines changed

core/src/main/kotlin/org/neo4j/graphql/SchemaBuilder.kt

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ object SchemaBuilder {
7979

8080
val handler = getHandler(config)
8181

82-
var targetSchema = augmentSchema(sourceSchema, handler)
82+
var targetSchema = augmentSchema(sourceSchema, handler, config)
8383
targetSchema = addDataFetcher(targetSchema, dataFetchingInterceptor, handler)
8484
return targetSchema
8585
}
@@ -128,7 +128,7 @@ object SchemaBuilder {
128128
return handler
129129
}
130130

131-
private fun augmentSchema(sourceSchema: GraphQLSchema, handler: List<AugmentationHandler>): GraphQLSchema {
131+
private fun augmentSchema(sourceSchema: GraphQLSchema, handler: List<AugmentationHandler>, schemaConfig: SchemaConfig): GraphQLSchema {
132132
val types = sourceSchema.typeMap.toMutableMap()
133133
val env = BuildingEnv(types, sourceSchema)
134134
val queryTypeName = sourceSchema.queryTypeName()
@@ -157,11 +157,11 @@ object SchemaBuilder {
157157
builder.clearFields().clearInterfaces()
158158
// to prevent duplicated types in schema
159159
sourceType.interfaces.forEach { builder.withInterface(GraphQLTypeReference(it.name)) }
160-
sourceType.fieldDefinitions.forEach { f -> builder.field(enhanceRelations(f, env)) }
160+
sourceType.fieldDefinitions.forEach { f -> builder.field(enhanceRelations(f, env, schemaConfig)) }
161161
}
162162
sourceType is GraphQLInterfaceType -> sourceType.transform { builder ->
163163
builder.clearFields()
164-
sourceType.fieldDefinitions.forEach { f -> builder.field(enhanceRelations(f, env)) }
164+
sourceType.fieldDefinitions.forEach { f -> builder.field(enhanceRelations(f, env, schemaConfig)) }
165165
}
166166
else -> sourceType
167167
}
@@ -177,7 +177,7 @@ object SchemaBuilder {
177177
.build()
178178
}
179179

180-
private fun enhanceRelations(fd: GraphQLFieldDefinition, env: BuildingEnv): GraphQLFieldDefinition {
180+
private fun enhanceRelations(fd: GraphQLFieldDefinition, env: BuildingEnv, schemaConfig: SchemaConfig): GraphQLFieldDefinition {
181181
return fd.transform { fieldBuilder ->
182182
// to prevent duplicated types in schema
183183
fieldBuilder.type(fd.type.ref() as GraphQLOutputType)
@@ -192,14 +192,21 @@ object SchemaBuilder {
192192
if (fd.getArgument(ProjectionBase.OFFSET) == null) {
193193
fieldBuilder.argument { a -> a.name(ProjectionBase.OFFSET).type(Scalars.GraphQLInt) }
194194
}
195-
if (fd.getArgument(ProjectionBase.ORDER_BY) == null && fd.type.isList()) {
196-
(fd.type.inner() as? GraphQLFieldsContainer)?.let { fieldType ->
197-
env.addOrdering(fieldType)?.let { orderingTypeName ->
198-
val orderType = GraphQLList(GraphQLNonNull(GraphQLTypeReference(orderingTypeName)))
199-
fieldBuilder.argument { a -> a.name(ProjectionBase.ORDER_BY).type(orderType) }
200-
}
195+
196+
val fieldType = fd.type.inner() as? GraphQLFieldsContainer ?: return@transform
197+
198+
if (fd.getArgument(ProjectionBase.ORDER_BY) == null) {
199+
env.addOrdering(fieldType)?.let { orderingTypeName ->
200+
val orderType = GraphQLList(GraphQLNonNull(GraphQLTypeReference(orderingTypeName)))
201+
fieldBuilder.argument { a -> a.name(ProjectionBase.ORDER_BY).type(orderType) }
202+
201203
}
202204
}
205+
206+
if (schemaConfig.query.enabled && !schemaConfig.query.exclude.contains(fieldType.name) && fd.getArgument(ProjectionBase.FILTER) == null) {
207+
val filterTypeName = env.addFilterType(fieldType)
208+
fieldBuilder.argument(input(ProjectionBase.FILTER, GraphQLTypeReference(filterTypeName)))
209+
}
203210
}
204211
}
205212

core/src/test/resources/augmentation-tests.adoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ schema {
396396
}
397397
398398
interface HasMovies {
399-
movies(first: Int, offset: Int, orderBy: [_MovieOrdering!]): [Movie]
399+
movies(filter: _MovieFilter, first: Int, offset: Int, orderBy: [_MovieOrdering!]): [Movie]
400400
}
401401
402402
type Knows0 @relation(direction : OUT, from : "source", name : "KNOWS", to : "knows") {
@@ -454,7 +454,7 @@ type Person4 {
454454
455455
type Person5 implements HasMovies {
456456
id: ID!
457-
movies(first: Int, offset: Int, orderBy: [_MovieOrdering!]): [Movie] @relation(direction : OUT, from : "from", name : "LIKES", to : "to")
457+
movies(filter: _MovieFilter, first: Int, offset: Int, orderBy: [_MovieOrdering!]): [Movie] @relation(direction : OUT, from : "from", name : "LIKES", to : "to")
458458
}
459459
460460
type Publisher {

core/src/test/resources/issues/gh-170.adoc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ CREATE
4242
[source,graphql]
4343
----
4444
query {
45-
r: rated( rating_gte : 3) {
45+
r: rated( filter: {rating_gte : 3}) {
4646
rating
4747
movie {
4848
title
@@ -55,7 +55,7 @@ query {
5555
[source,json]
5656
----
5757
{
58-
"rRatingGte" : 3
58+
"filterRRatingGte" : 3
5959
}
6060
----
6161

@@ -74,7 +74,7 @@ query {
7474
[source,cypher]
7575
----
7676
MATCH ()-[r:RATED]->()
77-
WHERE r.rating >= $rRatingGte
77+
WHERE r.rating >= $filterRRatingGte
7878
RETURN r {
7979
.rating,
8080
movie: head([()-[r]->(movie:Movie) | movie {

0 commit comments

Comments
 (0)