Skip to content
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

Support for cursor based pagination #106

Closed
mpgalaxy opened this issue Sep 3, 2019 · 8 comments
Closed

Support for cursor based pagination #106

mpgalaxy opened this issue Sep 3, 2019 · 8 comments

Comments

@mpgalaxy
Copy link

mpgalaxy commented Sep 3, 2019

Hi,

how can I use cursor based pagination (page=page, per_page=...) with your library ? I can't modify the mongo request using something like this:

def resolve_users(self, info):
    	return list(UserModel.objects.find({...}).sort(...).limit(limit))

because then I get 'QuerySet' object has no attribute 'find'

Please provide information regarding this functionality or implement this feature.

@stefanvanburen
Copy link

try using limit with skip:

def resolve_users(self, info):
    	return list(UserModel.objects(query).sort(...).skip(x).limit(limit))

you'll want to calculate the skip based on the page number and page size, of course

@mpgalaxy
Copy link
Author

mpgalaxy commented Sep 4, 2019

@svanburen : This is what I try to avoid. I want to use cursor based pagination with page and per_page params without the need of count(). I tried to use this library with pagination by flask_mongoengine, but it doesn't work. It inserts first:1 in the query which results in a Not a query object error:

def resolve_users(self, info, page=None):
    	return list(UserModel.objects(query).paginate(page=page, per_page=4))

If I try to query with skip and limit, I also get this type of error:

def resolve_users(self, info):
        return list(UserModel.objects(query).skip(5).limit(3))

Results in:

graphql.error.located_error.GraphQLLocatedError: Not a query object: 
    query {
        users {
            firstName,
            lastName
        }
    }
. Did you intend to use key=value?

Running the same query with .all() works perfectly fine.
The .objects(query) part seems to be the problem. Is there another way to interact with the mongo query using default mongo functions ?

@stefanvanburen
Copy link

It looks like in your case, you probably just want to omit the "query" parameter to .objects:

def resolve_users(self, info):
        return list(UserModel.objects().skip(5).limit(3))

@mpgalaxy
Copy link
Author

mpgalaxy commented Sep 5, 2019

@svanburen : This works, but how can I do a find() before limit ?
I need to be able to do a

return list(UserModel.objects().find({'_id' > last_id}).sort(sort).limit(per_page))

How can I do this with this library ?

@stefanvanburen
Copy link

@mpgalaxy perhaps something like this?:

return list(UserModel.objects(id__gte=last_id).sort(sort).limit(per_page))

for reference: http://docs.mongoengine.org/guide/querying.html#query-operators

also, I see that you're using '_id' - you may want to replace the id__gte above with whatever the primary key is defined in your UserModel (I put id above, but you'll want to replace that - so if it's user_id, do this:

return list(UserModel.objects(user_id__gte=last_id).sort(sort).limit(per_page))

)

hopefully that helps!

@mpgalaxy
Copy link
Author

mpgalaxy commented Sep 5, 2019

Thank you very much! :) I will give it a try tomorrow.
Currently I implemented pagination via skip and limit, which is suitable for small datasets:

def resolve_users(self, info, page=None, per_page=None):
        if page <= 0 or per_page <= 0:
            raise Exception("Values of page and per_page must be >0!")
        elif page == 1:
            return list(UserModel.objects.limit(per_page))
        else:
            return list(UserModel.objects.skip((page-1)*per_page).limit(per_page))

I have to make sure that the ids are sorted ascending. Currently the library returns them sorted ascending, but an option for that would be nice. ;) I'll report back on my results.

BTW: How can I send a 404 response with this lib ?
Throwing an Exception is not the best way to do this, because you still get status 200. ;)

BTW2: Is there a mutation example for flask ? In the example section I couldn't find one and I can't save my created user to the db, because it is a User object.

Thanks again and best regards ;)

@stefanvanburen
Copy link

I don't have a great answer for you for flask / 404s; typically in GraphQL rather than setting a HTTP response code you'll populate the errors dict, and I'd imagine the flask mutations wouldn't be so far from the other examples.

For sorting, you can use order_by to sort:

return list(UserModel.objects(user_id__gte=last_id).order_by(...).limit(per_page))

good luck!

@mpgalaxy
Copy link
Author

Hi, thank you very much, you really helped me a lot. I think I can close this issue now. ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants