smallrye-graphql icon indicating copy to clipboard operation
smallrye-graphql copied to clipboard

Limit, Paging Default Support for Resolvers returning lists

Open michaelsonnleitner opened this issue 5 years ago • 3 comments

Limit or the possibility to page a GraphQL Resolver is a common usecase.

It would be nice if this is a standard feature in the underlying graphql invoker of resolvers implemetation

following query:

query{
  p1: person(id: 1) {
    adresses(limit: 15, start: 0)
    { 
       street
    }
  }
}

should work with following resolver:

@GraphQLApi
public class PersonResource {

   @Inject
   AdressService adressService ;
   @Inject
   PersonRestApi personRestApi;

    @Query
    public Person getPerson(@Name("id") long id) throws ApiException, InterruptedException {
       Thread.sleep(2000);
        return personRestApi.load(id);
    }
   public List<Adress> getAdresses(@Source Person p) { 
      return adressService .getAdresses(p.getId());
   }
}

Result:

person 1 with the first 15 assigned adresses

The invoker of PersonResource .getAdresses(..) should limit and page the returning List<Adress> from 0 to 15. (imaging you have an legacy AdressService which can NOT limit, order, page the result on its own)

michaelsonnleitner avatar Oct 09 '20 09:10 michaelsonnleitner

Linked to https://github.com/eclipse/microprofile-graphql/issues/29. We can support this in SmallRye before we move this to the spec. Again, PR's are welcome :)

phillip-kruger avatar Oct 10 '20 09:10 phillip-kruger

Is there something special that is required for pagination?

I'm using this and that seems to work exactly as expected

    public Uni<List<Address>> addresses(@Source Person person, @Name("start") @DefaultValue("0") int start, @Name("limit") @DefaultValue("50") int limit) {
        return client.preparedQuery("""
                SELECT id, name FROM addresses WHERE person_id = $1 LIMIT $2 OFFSET $3""")
                .execute(Tuple.of(person.getId(), limit, start))
                .map(set -> Streams.stream(set)
                        .map(row -> new Address
                                row.getUUID("id"),
                                row.getString("name")
                        )).collect(Collectors.toList())
                );
    }

Then in docs under type Person the field addresses is documented as

addresses(start: Int = 0; limit: Int = 50): [Address]

diversit avatar Dec 29 '22 18:12 diversit

@diversit what you did is the only current way to do this. We are considering making this easier with a @Pagination annotation. But under the covers it will do what you did.

phillip-kruger avatar Jan 04 '23 00:01 phillip-kruger