- Switch to ES parent/child join_field: discussion docs hold all metadata,
post docs hold content only. Routing ensures parent and child land on the
same shard. Removes the old flat-document approach where post data was
duplicated onto every comment document.
- Add HasChildQuery with inner_hits so the best-matching post ID is
surfaced as mostRelevantPost without a second DB query.
- Blue-green index rebuilds: --recreate writes into a timestamped pending
index, --swap atomically promotes it via alias. Interrupted builds are
resumable with --recreate --continue. --swap requires confirmation before
proceeding.
- Index hidden posts; non-moderators are filtered at query time via
is_hidden on the has_child clause. Core\Hidden and Core\Restored trigger
re-indexing so moderators with post.hide can search hidden posts.
- Rename SavingJob to UpdateSearchJob
- Add ViewsSearchJob for lightweight partial view_count updates
- Add probabilistic sync throttle in DiscussionSeeder::viewingOn()
to avoid an ES update on every page view
- Add view_count to mapping, DiscussionSeeder::toDocument(), and
translateSort
- Log a warning and skip instead of 500ing on unknown sort fields
When all documents in a range were already in the index, the empty
collection caused continueAt to be set to null, aborting before
scanning lower ID ranges. Now advances past the range bottom instead.
Flarum's search UI enforces a minimum query length of 3 characters
(MIN_SEARCH_LEN in Search.tsx), so 1- and 2-character ngram tokens
are indexed but can never be queried. Changed min_gram from 1 to 3
and updated max_ngram_diff accordingly.