Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Add cursor pagination and filtering to `GET /api/v1/search`

Open
#216 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
50/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Active
Tech stack
elasticsearch, nodejs, typescript
Domain
api, backend, search

Research direction

Start with src/search/search.service.ts and src/search/search.controller.ts, then read the shared src/common/pagination/cursor-pagination.service.ts and its spec. Replace the untyped search and indexPost signatures with a DTO in src/search/dto/search.dto.ts, and add mocked Elasticsearch unit tests for paging, filtering and the limit ceiling. Done means GET /search returns { results, nextCursor, total }, an oversized limit returns 400, and docs/openapi.json is regenerated.

Written by the indexing model from the issue text.

Description

enhancement help wanted intermediate performance

Problem

src/search/search.service.ts is a 27-line stub with two methods and no pagination, no filtering, and no size limit:

async search(query: string) {
  const result = await this.esService.search({
    index: "posts",
    query: { multi_match: { query, fields: ["title", "content"] } },
  });
  return result.hits.hits.map((hit) => hit._source);
}

Elasticsearch defaults to 10 results per request, so this silently truncates — and because there is no size or from, a caller asking for more than 10 results cannot get them at all. indexPost(post: any) also takes an untyped parameter, and src/search/search.controller.ts exposes only POST /search/index and GET /search.

Separately, the repo already has a working cursor-pagination implementation at src/common/pagination/cursor-pagination.service.ts with a spec, and the README documents cursor pagination as the standard for the GraphQL gateway. Search should use the same convention.

Why it matters

This is the only search entry point, and it is effectively unusable for anything beyond browsing the first ten hits. Users cannot paginate, filter by field, sort, or get a total count — all standard expectations for a search endpoint, and all things the generated SDK is expected to expose.

Suggested Direction

  1. Reuse the existing pagination utility. Read src/common/pagination/cursor-pagination.service.ts and use its cursor scheme for consistency rather than inventing offset pagination.
  2. Add a typed search DTO (src/search/dto/search.dto.ts) with q, limit (with a @Max() ceiling — see the pagination-bounds issue), cursor, and filter/sort fields, replacing search(query: string) and indexPost(post: any).
  3. Add filtering by whatever fields the indexed documents actually carry. Check what populates the posts index before deciding — if nothing does, that is a separate bug worth filing.
  4. Return metadata, not a bare array: { results, nextCursor, total }. The current bare-array return is why the GraphQL gateway had to add pagination separately (see docs/GRAPHQL_GATEWAY.md).
  5. Set an explicit size, and consider track_total_hits if a total count is returned.

Constraints

  • Keep the existing index name (posts) and field mappings (title, content) unless there is a reason to change them; changing the mapping requires a reindex.
  • Guard against unbounded size so a client cannot request an enormous result set.
  • ElasticsearchService is already a dependency — do not add a new Elasticsearch client.
  • Update docs/openapi.json via npm run openapi:export.

Acceptance Criteria

  • GET /search accepts a typed query DTO and returns { results, nextCursor, total }.
  • Pagination uses the shared cursor utility; a limit above the ceiling returns 400.
  • indexPost no longer takes an any parameter.
  • Results beyond the first page are retrievable via cursor.
  • Unit tests cover paging, filtering, and the limit ceiling with a mocked Elasticsearch service.
  • npm run openapi:export is regenerated.
Dominant language
TypeScript
Stars
7
Forks
55
Avg merge
1d 17h
Merged PRs (30d)
5

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from SourceXXL/alian_structure-api

All issues in SourceXXL/alian_structure-api

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.