Skip to content

feat(search): extend document search to content + add time range and sort filters (#68) - #69

Merged
PeterGuy326 merged 4 commits into
bytefolk:mainfrom
sun-970:feat/multi-dimensional-search
Sep 18, 2026
Merged

PeterGuy326 merged 4 commits into
bytefolk:mainfrom
sun-970:feat/multi-dimensional-search

Conversation

@sun-970

@sun-970 sun-970 commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #68 (Phase 1 + Phase 2).

  • Content search: GET /api/doc?keyword=X and GET /api/v1/documents?query=X now search both title AND content (OR), not just title. Uses Prisma OR + contains with mode: 'insensitive' — no schema migration needed.
  • Time range filters: after and before query params filter by updatedAt (ISO 8601 dates). Invalid dates return 400.
  • Sort options: sort query param accepts updated_desc (default), updated_asc, created_desc, created_asc. Invalid values return 400.
  • Shared query module: Extracted doc-query.ts with shared parseOptionalDate, parseSort, buildSearchWhere, buildDateWhere, getOrderBy helpers used by both routes.

Changes

File What changed
src/lib/doc-query.ts New shared query parser and where/orderBy builders
src/lib/api-v1-documents.ts Uses shared helpers; cursor pagination disabled for created_* sorts
src/app/api/doc/route.ts Uses shared helpers; returns 400 for invalid date/sort; title search now case-insensitive
src/__tests__/lib/api-v1-documents.test.ts Updated existing test assertion for new OR shape; added 5 new tests

API contract

GET /api/v1/documents (new query params)

Param Type Default Description
query string Searches title OR content (case-insensitive)
after ISO 8601 updatedAt > after (400 if invalid)
before ISO 8601 updatedAt < before (400 if invalid)
sort enum updated_desc updated_desc, updated_asc, created_desc, created_asc (400 if invalid)

GET /api/doc (new query params)

Param Type Default Description
keyword string Searches title OR content (case-insensitive)
after ISO 8601 updatedAt > after (400 if invalid)
before ISO 8601 updatedAt < before (400 if invalid)
sort enum updated_desc Same as v1 (400 if invalid)

Test plan

  • npx vitest run — 333 tests pass (5 new)
  • npx tsc --noEmit — no TypeScript errors
  • Manual: search for a keyword that only exists in document body via the search dialog
  • Manual: verify after/before/sort params via API v1 with a PAT

Out of scope (Phase 3+)

…sort filters (bytefolk#68)

- Internal GET /api/doc and API v1 GET /api/v1/documents now search both
  title and content (OR) instead of title-only
- Add after/before query params for updatedAt range filtering
- Add sort query param (updated_desc|updated_asc|created_desc|created_asc)
- No schema migration needed — uses Prisma OR + contains

@PeterGuy326 PeterGuy326 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

REQUEST CHANGES\n\n当前 head 需要先修复以下阻断和契约不一致:\n\n1. 构建不通过。src/lib/api-v1-documents.ts:143-154 的 getOrderBy 返回 readonly tuple,src/lib/api-v1-documents.ts:241 传给 Prisma orderBy 时触发 TS2322。已在本地 npx tsc --noEmit 复现;GitHub CI 的 docker-build 也因同一错误失败。请返回可赋给 Prisma orderBy 的可变数组类型,并补充构建验证。\n\n2. 搜索大小写行为不一致。src/app/api/doc/route.ts:240-242 的 title 条件没有 mode: insensitive,但 content 条件有;v1 入口两者都有。内部 GET /api/doc 的标题搜索因此大小写敏感,请统一。\n\n3. 参数校验行为不一致。src/app/api/doc/route.ts:216-247 对非法 after/before 生成 Invalid Date 后静默省略条件,:250-256 对非法 sort 静默回退 updated_desc;v1 入口对两者都返回 400 invalid_query。两个入口应共享解析/校验逻辑,并补充内部 route 的 400 回归测试。\n\n4. created_* 排序和游标分页不匹配。src/lib/api-v1-documents.ts:63-66、225-255 的 cursor 只保存/比较 updatedAt + id,但 getOrderBy 已允许按 createdAt 排序。使用 created_asc 或 created_desc 翻第二页时仍按 updatedAt 过滤,可能重复或漏项。请让 cursor 带 sort 相关字段并使用对应比较条件,或暂时禁止这些 sort 的 cursor 分页,并补充第二页测试。\n\n5. 两套路由仍各自维护 where/orderBy 构建:src/app/api/doc/route.ts:210-271 与 src/lib/api-v1-documents.ts:192-243。当前差异已经造成上述搜索和校验不一致,建议抽取共享的 query parser、where builder 和 orderBy builder。\n\n验证:PR head db8ecb8 已在本地核对;v1 service 15 tests 与 v1 route 6 tests 通过,npx tsc --noEmit 失败并复现上述 TS2322。GitHub CI 的 test 312 tests 通过,但 docker-build 失败。PR 描述中的内部搜索、时间范围、sort 手工验证仍未完成,本次 diff 也没有 CHANGELOG.md 的 [Unreleased] 条目。修复并补齐验证后请通知复审。

…or pagination

- Extract shared doc-query.ts module for query parsing and where/orderBy builders
- Fix getOrderBy to return mutable array (TS2322 build failure)
- Add mode: insensitive to /api/doc title search for consistency with v1
- Return 400 for invalid date/sort params instead of silently ignoring
- Disable cursor pagination for created_* sort orders (cursor is updatedAt-based)
- Unify search/date/sort logic between /api/doc and /api/v1/documents

@PeterGuy326 PeterGuy326 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复核当前 head c013bfd:此前列出的查询逻辑、校验、大小写搜索和 created_* 游标问题已按当前 diff 处理;当前真正阻断的是 CI 的 test job:npm run format 只报 src/lib/doc-query.ts 需要 Prettier 格式化。我在隔离工作树复现了同一格式告警,格式化后仅有该文件的排版变化;但无法直接推送到作者 fork,请运行 npx prettier --write src/lib/doc-query.ts 后提交并 request re-review。另请补齐 CHANGELOG.md [Unreleased] 条目和内部搜索/时间范围/sort 的手工验证记录。

@waterbro-8 waterbro-8 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review

CI: test failed on npm run format — Prettier wants src/lib/doc-query.ts rewritten. docker-build passed.

Must fix

  • Run npx prettier --write src/lib/doc-query.ts (or npm run format:fix) and push. CI dies before tests.

Scope (ok if documented)

  • This is Phase 2 of #68 (title OR content contains, after/before/sort), not tsvector / matchField. That follow-up is #71. Please do not close #68 as fully done, or split the issue.
  • Searching TipTap JSON with contains will miss some body hits and can match markup. Fine as the no-migration path; say so in the API docs (docs/API.md is unchanged).

Nice

  • Rejecting created_* sort with cursor pagination is the right fail-closed choice.
  • Invalid date/sort tests are present.

Verdict: request changes until format CI is green. After that this is a reasonable Phase-2 merge.

@sun-970

sun-970 commented Sep 18, 2026

Copy link
Copy Markdown
Contributor Author

Changes pushed: Prettier format fixed, CHANGELOG entry added, CI green. Ready for re-review.

@waterbro-8 waterbro-8 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review

Previous blockers are addressed on the current head:

  • getOrderBy returns a mutable Prisma array
  • title and content search both use mode: insensitive
  • invalid after / before / sort return 400 via shared doc-query.ts
  • created_* + cursor is fail-closed (400)
  • Prettier on doc-query.ts is clean
  • CHANGELOG [Unreleased] is present
  • CI (test + docker-build) is green

Residual (non-blocking)

  • /api/doc 400 paths are not covered by tests (only v1 listApiDocuments is). Worth one invalid-sort/date case on the internal route.
  • after > before is not rejected.
  • TipTap JSON contains will miss some body hits and can match markup. Acceptable as the no-migration Phase 2 path; keep full-text / matchField on #71. Do not close #68 as fully done unless Phase 3 is explicitly dropped.
  • Host-app API docs are a separate follow-up (#77).

Verdict: approve as Phase 2 of #68.

@PeterGuy326 PeterGuy326 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed current head f3ed1c3.

  • Required CI is green; Prettier format and TypeScript checks pass.
  • Focused API/document-route tests pass (21 tests).
  • Shared query parsing covers title/content search, date bounds, sort validation, and invalid-input 400 responses; current diff has no remaining blocking finding.
  • Existing CODEOWNER approval is present; the remaining merge blocker is the repository's expected CodeQL (javascript-typescript) context on fork PRs.

@PeterGuy326
PeterGuy326 merged commit fd6b4d7 into bytefolk:main Sep 18, 2026
5 checks passed
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.

Upgrade document search to multi-dimensional indexed retrieval (content, time, metadata)

3 participants