Skip to content

Return @search.nextPageParameters when a search leaves out top - #100

Open
danielgreen wants to merge 3 commits into
feature23:mainfrom
danielgreen:feature/next-page-parameters
Open

danielgreen wants to merge 3 commits into
feature23:mainfrom
danielgreen:feature/next-page-parameters

Conversation

@danielgreen

@danielgreen danielgreen commented Oct 21, 2026 •

Copy link
Copy Markdown

Fixes #103

What was wrong

A POST search without top returned the first 50 results and no way to get the rest. Azure returns the same 50 plus @search.nextPageParameters and @odata.nextLink when more results match. The Azure Search SDKs follow these to read every result, so a client that enumerated a search saw only 50.

What changed

  • SearchRequest.Top is now null when the request leaves it out, so the searcher can tell that apart from top: 50. SearchRequest.DefaultTop is 50.
  • When top was left out and more results match, the searcher reports the next skip. The controller returns the same request with skip moved on and still no top, so each page gets a continuation of its own, plus @odata.nextLink to docs/search.post.search.
  • A request that sets top gets no continuation, as in Azure.
  • No continuation is offered once its skip would pass 100,000 (SearchRequest.MaxSkip), since the emulator refuses that skip with 400. The client stops after the last page it can request.

Not covered: GET searches, where Azure returns only a nextLink to another GET, and top above 1000, which still returns 400.

Tests

  • SearchPagingTests (new, unit, 8 tests): the first page and its next skip; following each continuation over 120 documents gives pages of 50, 50 and 20 with every document once; no continuation when the matches fit on one page or when top is set; and, over 100,100 documents, a continuation at the skip limit but none past it.
  • SearchPagingIntegrationTests (new, 3 tests, against the container through the .NET SDK): enumerating without Size reads all 120 in pages of 50, 50 and 20; Size = 50 reads 50; the REST response has skip: 50, no top, the original search and filter, and the nextLink.
  • DebugClient check 10 (new): uploads 120 more documents and reads every result through the SDK's paging, in pages of 50, 50 and 23. It reads only 50 of 123 on main.
  • Also checked by hand with the Python SDK azure-search-documents 11.5.2: a search with no top yields all 120 results.

All 981 unit tests pass.

dotnet test from the repo root currently stops before any test runs, on main too: restoring AzureSearchEmulator.Aspire fails with NU1902, a moderate advisory for MessagePack 2.5.302 (GHSA-qhrr-8q5h-9q3h) that the project treats as an error. I ran the unit and integration test projects directly.

A POST search without top returned the first 50 results and no way to
get the rest. Azure returns the same 50, plus @search.nextPageParameters
and @odata.nextLink when more results match. The Azure Search SDKs
follow these to read every result, so a client that enumerated a
search saw only 50.

SearchRequest.Top is now null when the request leaves it out, so the
searcher can tell that apart from top: 50. The continuation is the
same request with skip moved on and still no top, so each page gets a
continuation of its own. A request that sets top gets no continuation,
as in Azure.

Not covered: GET searches, where Azure returns only a nextLink to
another GET, and top above 1000, which still returns 400.
A search without top that started within 50 of skip 100,000, over more
matches than that, returned @search.nextPageParameters with a skip
above 100,000. Sending it back was refused with 400, so an SDK reading
the results would throw part way through. Now no next page is offered
once its skip would pass the limit, and the client stops after the
last page it can request.

The limit is SearchRequest.MaxSkip, which the controller's check uses
too.
Check 10 uploads 120 more documents and searches with no Size, then
follows each page through the SDK. It passes when every document is
read: 123 in pages of 50, 50 and 23. Deleting the index becomes
check 11.
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

Successfully merging this pull request may close these issues.

A search without top returns 50 results and no @search.nextPageParameters

1 participant