@@ -78,6 +78,7 @@ class Translator(val schema: GraphQLSchema) {
7878 (params + mapProjection.params))
7979 }
8080
81+
8182 private fun propertyArguments (queryField : Field ) =
8283 queryField.arguments.filterNot { listOf (" first" , " offset" , " orderBy" ).contains(it.name) }
8384
@@ -90,7 +91,7 @@ class Translator(val schema: GraphQLSchema) {
9091 }
9192
9293 private fun where (variable : String , field : GraphQLFieldDefinition , type : GraphQLType , arguments : List <Argument >) : Cypher {
93- val all = preparePredicateArguments(field, arguments)
94+ val all = preparePredicateArguments(field, arguments).filterNot { listOf ( " first " , " offset " , " orderBy " ).contains(it.name) }
9495 if (all.isEmpty()) return Cypher (" " )
9596 val (filterExpressions, filterParams) =
9697 filterExpressions(all.find{ it.name == " filter" }?.value, type as GraphQLObjectType )
@@ -216,7 +217,7 @@ class Translator(val schema: GraphQLSchema) {
216217 val parentIsRelationship = parent.definition.directivesByName.containsKey(" relation" )
217218 return when (parentIsRelationship) {
218219 true -> projectRelationshipParent(variable, field, fieldDefinition, parent, ctx)
219- else -> projectRichAndRegularRelationship(variable, field, fieldDefinition, ctx)
220+ else -> projectRichAndRegularRelationship(variable, field, fieldDefinition, parent, ctx)
220221 }
221222 }
222223
@@ -234,28 +235,31 @@ class Translator(val schema: GraphQLSchema) {
234235 return Cypher (comprehension + slice, (expression.params + fieldProjection.params)) // + where.params
235236
236237 }
237- private fun projectRichAndRegularRelationship (variable : String , field : Field , fieldDefinition : GraphQLFieldDefinition , ctx : Context ): Cypher {
238+ private fun projectRichAndRegularRelationship (variable : String , field : Field , fieldDefinition : GraphQLFieldDefinition , parent : GraphQLObjectType , ctx : Context ): Cypher {
238239 val fieldType = fieldDefinition.type
239240 val fieldObjectType = fieldType.inner() as GraphQLObjectType
240241 // todo combine both nestings if rel-entity
241- val (relDirective, relFromType ) = fieldObjectType.definition.getDirective(" relation" )?.let { it to true }
242+ val (relDirective, isRelFromType ) = fieldObjectType.definition.getDirective(" relation" )?.let { it to true }
242243 ? : fieldDefinition.definition.getDirective(" relation" )?.let { it to false }
243244 ? : throw IllegalStateException (" Field $field needs an @relation directive" )
244245
245- val (relType, outgoing, endField) = relDetails(relDirective)
246- val (inArrow, outArrow) = arrows(outgoing)
246+ var relInfo = relDetails(fieldObjectType, relDirective)
247+ val inverse = isRelFromType && fieldObjectType.getFieldDefinition(relInfo.startField).type.inner().name != parent.name
248+ if (inverse) relInfo = relInfo.copy(out = relInfo.out ?.let { ! it }, startField = relInfo.endField, endField = relInfo.startField)
249+
250+ val (inArrow, outArrow) = relInfo.arrows
247251
248252 val childVariable = variable + field.name.capitalize()
249253
250254 val endNodePattern = when {
251- relFromType -> {
252- val label = fieldObjectType.getFieldDefinition(endField).type.inner().name
253- " $childVariable${endField.capitalize()} :$label "
255+ isRelFromType -> {
256+ val label = fieldObjectType.getFieldDefinition(relInfo. endField!! ).type.inner().name
257+ " $childVariable${relInfo. endField!! .capitalize()} :$label "
254258 }
255259 else -> " $childVariable :${fieldObjectType.name} "
256260 }
257261
258- val relPattern = if (relFromType ) " $childVariable :${relType } " else " :${relType } "
262+ val relPattern = if (isRelFromType ) " $childVariable :${relInfo.type } " else " :${relInfo.type } "
259263
260264 val where = where(childVariable, fieldDefinition, fieldObjectType, propertyArguments(field))
261265 val fieldProjection = projectFields(childVariable, field, fieldObjectType, ctx)
@@ -270,14 +274,17 @@ class Translator(val schema: GraphQLSchema) {
270274 val fieldType = fieldDefinition.type
271275 val fieldObjectType = fieldType.inner() as GraphQLObjectType
272276 val relDirective = parent.definition.directivesByName.getValue(" relation" )
273- val (_, _, endField) = relDetails(relDirective)
277+ var relInfo = relDetails(fieldObjectType, relDirective)
278+
279+ val inverse = parent.getFieldDefinition(relInfo.endField!! ).type.inner().name != fieldObjectType.name
280+ if (inverse) relInfo = relInfo.copy(out = relInfo.out ?.let { ! it }, startField = relInfo.endField, endField = relInfo.startField)
274281
275- val fieldProjection = projectFields(variable + endField.capitalize(), field, fieldObjectType, ctx)
282+ val fieldProjection = projectFields(variable + relInfo. endField!! .capitalize(), field, fieldObjectType, ctx)
276283
277284 return Cypher (fieldProjection.query)
278285 }
279286
280- private fun relDetails (relDirective : Directive ) = relDetails(relDirective, schema)
287+ private fun relDetails (target : GraphQLObjectType , relDirective : Directive ) = relDetails(target, relDirective, schema)
281288
282289 private fun slice (skipLimit : Pair <Int , Int >, list : Boolean = false) =
283290 if (list) {
0 commit comments