Skip to content

feat: index-backed /search (jieba/CJK, ranked, visibility-filtered)#239

Merged
sufforest merged 1 commit into
mainfrom
wzy/search-index-query
Jul 4, 2026
Merged

feat: index-backed /search (jieba/CJK, ranked, visibility-filtered)#239
sufforest merged 1 commit into
mainfrom
wzy/search-index-query

Conversation

@sufforest

Copy link
Copy Markdown
Owner

PR 2 of the full-text search feature. PR 1 (#237) added the inverted index; this rewrites POST /v3/search to actually use it, replacing the substring scan.

What changes

  • Query is jieba-tokenized the same way the index is, so CJK searches match word-by-word (你好世界 → 你好/世界). Multi-term queries AND-intersect postings.
  • order_by: rank sums term frequency; recent sorts by time. keys (body/name/topic) and filter.senders/filter.rooms are honored.
  • History-visibility: every hit AND its before/after context events pass the per-event gate (TimelineReadGate::permits). The old substring version gated neither the hit nor the context, so context could leak pre-join (under joined visibility) or post-leave events — closed here. Redacted and E2EE-room events excluded.
  • Predecessor-chain search, pagination, and context building are kept.

Tests (tests/search_index_query.rs): body + CJK + multi-term AND + keys filter, rank-by-term-frequency ordering, and a negative-space test that a pre-join message does not leak into a hit's context under joined visibility.

Known limitation: the per-token candidate cap (1000, newest-first) means a common + rare AND query can miss an old match whose common token falls outside the recent window — same recency-window bound the old scan had. A rarest-token-first intersection is a later optimization.

A reviewer pass flagged the context-visibility gap (now fixed) and confirmed the AND-intersection, keys filter, pagination safety, and filter.rooms handling are correct.

rewrites POST /search to match against the inverted index instead of a
substring scan over the last 1000 timeline events. the query is jieba-
tokenized the same way the index is, so CJK searches work word-by-word;
multi-term queries AND-intersect postings; order_by rank sums term
frequency; the keys and filter.senders filters are honored.

every hit AND its before/after context events pass the per-event
history-visibility gate (the substring version gated neither, so context
could leak pre-join / post-leave events); redacted and E2EE-room events
are excluded.
@sufforest sufforest merged commit 5673aff into main Jul 4, 2026
11 checks passed
@sufforest sufforest deleted the wzy/search-index-query branch July 4, 2026 13:38
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.

1 participant