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

Cosmos: add support for pagination #24513

Closed
AndriySvyryd opened this issue Mar 25, 2021 · 18 comments · Fixed by #34103
Closed

Cosmos: add support for pagination #24513

AndriySvyryd opened this issue Mar 25, 2021 · 18 comments · Fixed by #34103
Assignees
Labels
area-cosmos area-query closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported punted-for-7.0 Originally planned for the EF Core 7.0 (EF7) release, but moved out due to resource constraints. type-enhancement
Milestone

Comments

@AndriySvyryd
Copy link
Member

See https://docs.microsoft.com/en-us/dotnet/api/microsoft.azure.cosmos.queryrequestoptions.maxitemcount?view=azure-dotnet

@AndriySvyryd
Copy link
Member Author

Also consider exposing the continuation token

The RU charge of a query with OFFSET LIMIT will increase as the number of terms being offset increases. For queries that have multiple pages of results, we typically recommend using continuation tokens. Continuation tokens are a "bookmark" for the place where the query can later resume. If you use OFFSET LIMIT, there is no "bookmark". If you wanted to return the query's next page, you would have to start from the beginning.

@ajcvickers
Copy link
Member

/cc @roji

@roji
Copy link
Member

roji commented Oct 28, 2021

It seems like we should have both a per-query setting and a global context option default (like non-tracked).

Some theoretical thoughts:

  • This is related to keyset pagination in the sense that this is also about avoiding OFFSET pagination.
  • The rough relational feature comparable to this is cursors, i.e. execute a query via a cursor (DECLARE CURSOR FOR ...) and then fetching the next page each time (FETCH NEXT ...). In both cases we're executing a roundtrip every time to get the next page. It's interesting that this logic is the default in Cosmos but not in relational.
  • We could provide a relational feature where the query is paginated: the application would continue interacting with a simple QueryingEnumerable, and EF would send FETCH NEXT as needed under the hood.
  • However, I'm not sure how that's better than the application implementing explicit keyset navigation itself, i.e. using OrderBy and Where to precisely define the page they want to fetch.
    • Explicit keyset pagination has the advantage of being able to move backwards (whereas a LINQ Enumerable can only move forward).
    • Cursors would have to be closed when the enumerable is disposed. This means the consuming application (e.g. GraphQL) must hold state during the pagination, which doesn't fit well with the disconnected model. Explicit keyset navigation doesn't require this - you just need to provide data on the row fetched in the last page, and go from there.
    • There may be some perf advantages in using cursors (same query being executed rather than multiple ones), but it isn't very clear at this point.
  • Some differences between relational cursors and Cosmos continuation tokens:
    • A Cosmos continuation token doesn't hold up any server-side resources, whereas a relational cursor must be closed.
    • Cosmos is free to return less than MaxItemCount, so if the goal is to definitely return a page of 10, the application is responsible for refetching (EF in our scenario).

@ajcvickers ajcvickers added punted-for-7.0 Originally planned for the EF Core 7.0 (EF7) release, but moved out due to resource constraints. and removed propose-punt labels Jul 7, 2022
@ajcvickers ajcvickers modified the milestones: 7.0.0, Backlog Jul 7, 2022
@smitpatel smitpatel removed their assignment Sep 14, 2022
@jhulbertpmn
Copy link

Very interested in this - currently using EFCore + Cosmos provider in a Blazor Server application and there isn't a very scalable way I can find to offer paging without being able to use the continuation token

@vyarymovych
Copy link

Very interested in this as well. We are using EF Core Cosmos provider at the moment and the only way to query a page is to use the 'skip and take' approach. But as it has been mentioned, it's going to use more RUs for the next pages.

So we started thinking about using .NET SDK and replacing EF queries with Cosmos continuation tokens

@brandonsmith86
Copy link

Any updates? I am also having to shelve EF w/ Cosmos because of this limitation.

@AndriySvyryd
Copy link
Member Author

This feature hasn't been assigned to a particular release yet. The best way to indicate the importance of an issue is to vote (👍) for it. This data will then feed into the planning process for the next release.

@AndriySvyryd
Copy link
Member Author

AndriySvyryd commented Dec 2, 2023

Current design proposal:

    public static Task<Page<TSource>> ToPageAsync<TSource>(
        this IQueryable<TSource> source,
        string? continuationToken = null,
        int? maxItemCount = null,
        int? continuationTokenLimitInKb = null,
        CancellationToken cancellationToken = default)
 
    public static IQueryable<TSource> WithMaxItemCount<TSource>(
        this IQueryable<TSource> source,
        int maxItemCount)

See Page<T>
Aslo see Pagination with the Azure SDK

Open questions:

  • Naming

@roji
Copy link
Member

roji commented Dec 4, 2023

Thanks @AndriySvyryd, was not aware of this API!

@roji
Copy link
Member

roji commented Dec 4, 2023

Note the conceptually somewhat similar LINQ Chunk API which was recently added. Of course, that has no notion of a continuation token, so is less useful.

@roji
Copy link
Member

roji commented Dec 4, 2023

BTW we could even consider providing some sort of similar "pageability" on relational databases via keyset pagination, where the sorting key(s) would be somehow encoded as the continuation token which the user can extract and pass back.

@AndriySvyryd
Copy link
Member Author

AndriySvyryd commented Dec 4, 2023

Updated the proposal based on the discussion. If we implement pagination on other providers the API will be separate, even if the general shape is the same, to allow exposing provider-specific options.

@roji
Copy link
Member

roji commented Dec 4, 2023

BTW I think it does make sense to accept the maxItemCount directly in ToPageAsync, just to not force the user to use two different operators (it could override any previous-specified one). But we can figure all that out later.

@ajcvickers ajcvickers modified the milestones: Backlog, 9.0.0 May 8, 2024
@ajcvickers ajcvickers self-assigned this May 8, 2024
@KrzysztofCwalina
Copy link
Member

It would be good if you used the same patter, or even the same pagination API as in the Azure SDK (or System.ClientModel).

@roji
Copy link
Member

roji commented Jun 5, 2024

@KrzysztofCwalina yeah, we haven't yet started designing for this, but these are on my radar. Are you refering specifically to these recently-merged paging abstractions, or anything else?

@annelo-msft
Copy link
Member

@roji, we are iterating to finalize those abstractions now in advance of the next GA of System.ClientModel. If those or the similar types in Azure.Core don't meet your requirements but you'd be open to using them if they did, it would be helpful to us to understand your requirements so we could consider including them in the SCM abstractions with a goal to minimize API surface for users.

@roji
Copy link
Member

roji commented Jun 5, 2024

Sounds good! I'll try to prioritize working on the pagination bits sooner rather than later, and will be in touch with the results. Who are the relevant people to ping on both System.ClientModel and the Azure SDKs, apart from you two?

@annelo-msft
Copy link
Member

annelo-msft commented Jun 5, 2024

Who are the relevant people to ping on both System.ClientModel and the Azure SDKs, apart from you two?

@KrzysztofCwalina and I are a great place to start and we can loop in anyone else whose perspective we need. Many thanks!

@roji roji changed the title Cosmos: add support for pagination (MaxItemCount) Cosmos: add support for pagination Jun 27, 2024
roji added a commit to roji/efcore that referenced this issue Jun 27, 2024
roji added a commit to roji/efcore that referenced this issue Jun 27, 2024
roji added a commit to roji/efcore that referenced this issue Jun 27, 2024
roji added a commit to roji/efcore that referenced this issue Jun 27, 2024
roji added a commit to roji/efcore that referenced this issue Jun 28, 2024
roji added a commit to roji/efcore that referenced this issue Jun 28, 2024
roji added a commit to roji/efcore that referenced this issue Jun 28, 2024
@roji roji added closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. area-query and removed needs-design consider-for-current-release labels Jul 1, 2024
@roji roji closed this as completed in fee7c1a Jul 1, 2024
@ajcvickers ajcvickers modified the milestones: 9.0.0, 9.0.0-preview7 Jul 8, 2024
@ajcvickers ajcvickers removed their assignment Sep 1, 2024
@roji roji modified the milestones: 9.0.0-preview7, 9.0.0 Oct 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-cosmos area-query closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported punted-for-7.0 Originally planned for the EF Core 7.0 (EF7) release, but moved out due to resource constraints. type-enhancement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants