arangodb-graphql-spring-boot-starter icon indicating copy to clipboard operation
arangodb-graphql-spring-boot-starter copied to clipboard

issue filtering on nested

Open gmjordan opened this issue 5 years ago • 3 comments

I followed the filtering example and I am not sure if the results are what is to be expected.

I have two types

type country @vertex(collection: "countries"){
    _key: String!
    name: String!
    states(region:String): [state] @edge (collection: "stateToCountry", direction: "inbound")
}
type state @vertex(collection: "states"){
    _key: String!
    name: String!
    region: String!
    countries: [country] @edge (collection: "stateToCountry", direction: "outbound")
}

the queries are

findState(name: String): [state]
findCountry(name: String): [country]

when I run the following:

query{
	findCountry{
	    name
	    states(region:"South"){
	        name
	        region
	    }
	}
}

it returns all the countries.

based on the docs, it seemed that it would only return countries where the state had a region of "South"

am I reading the docs wrong or applying the filter incorrectly?

gmjordan avatar Jan 23 '20 05:01 gmjordan

I think that would be the behaviour I would expect. Reading the documentation though - I think the example is misleading - so I will update it

The filters are applied at the part of the query where the arguments are specified (and its children) it doesn't filter the parent entities. Is that what you are looking to do?

colinfindlay avatar Feb 16 '20 23:02 colinfindlay

The filters are applied at the part of the query where the arguments are specified (and its children) it doesn't filter the parent entities. Is that what you are looking to do?

i am looking filter parents that have children with the same properties

gmjordan avatar Feb 17 '20 15:02 gmjordan

I think this is a common GraphQL problem - mostly down to how resolvers generally work.

For example: https://github.com/graphql-python/graphene/issues/431 https://www.prisma.io/forum/t/filter-query-by-field-on-nested-type/1495

One challenge specific to this library with doing this is expressing it as AQL. The current behaviour means that you can have multiple traversals following different edge collections at the same level in your GraphQL

i.e. it would allow me to write something like this where I want the states but also some census information. I haven't applied a filter on country so I expect to get all the countries and their census information.

query{
	findCountry{
	    name
	    states(region:"South"){
	        name
	        region
	    }
            census(year: 2020){
                population
           }
	}
}

The TraversalFilterGenerator generates a filter statement that ties the submitted filter to the edge it was submitted against to allow this to happen. I'm convinced this is a sensible default behaviour as it is in line with how resolvers generally operate.

My advice would be you have two possible ways of achieving the behaviour you want.

One - turn the query on it's head - do this instead:

query{
	findState(region: "South"){
	    name
            region
            country {
                name
            }
	}
}

OR option two, modify the default behavior.

If you want to change the filtering behaviour you can do it by creating a bean of type ArangoQueryGeneratorChain (it uses DefaultArangoQueryGeneratorChain by default) and wiring in your own implementation of an AQL Filter generator by implementing ArangoQueryGenerator to write the AQL you wish to use. If you look at AbstractQueryGenerator as a guide, you will likely be able to achieve your desired result by removing the following lines in the filter() method, as that is the part of the query that allows for the flexibility I described above.

            sb.append(" OR (NOT ");
            sb.append(isSameCollection.toString());
            sb.append(")");

This would leave you with a limitation of only one traversal per level of your GraphQL schema - but that looks fine from your example above.

Hope that helps CF

colinfindlay avatar Feb 19 '20 00:02 colinfindlay