The flag-based interface (--rebuild etc) became rather convoluted with the changes. Replace this with commands with more straight forward naming.
Also added an explicit 'rollback' action and updated the README.md
- 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.
content_partial was introduced alongside a partialMatch() query that
targeted it. That query was later switched to use the content field
instead, but content_partial was never removed from the seeders,
causing every document to store and index its content twice.
When navigating to /t/{tag}?q=query the tag filter from the request
was silently ignored. Added a TermsQuery on the tags field using the
tag IDs resolved from the provided slugs.