Search: Add DisjointFacetEngine, FilterBuilder, FacetCache, and search groups
Review Request #15052 — Created May 13, 2026 and updated — Latest diff uploaded
Adds the core faceted search engine, the
reviewboard/search/facets/package,
along with benchmark tooling for performance validation.Key components:
-DisjointFacetEngine(aggregations.py) builds and executes a single
Elasticsearchmsearchbody per request containing: a paginated results
query, one aggregation sub-query perfaceted=TrueFilterSpec(each
excluding its own filter clause so bucket counts remain accurate when the
filter is active — the disjoint property), and one option-count query per
compound filter choice.
-FilterSpec/FilterBuilder(schema.py,builder.py) provide a
declarative schema for filter dimensions and translate active filter values
into Elasticsearchbool.filterclauses. Compound filters (ship-it, issues,
reviews, file attachments) use custombuild_fncallables.
-FacetCache(cache.py) caches aggregation results per group, query, and
filter state for the lifetime of a request.
-FacetedSearchEngine(engine.py) orchestrates searches across
ReviewRequestSearchGroup,UserSearchGroup, andReviewGroupSearchGroup.
For the active group it runs a full search with aggregations; for inactive
groups it runs a count-only query so sidebar tab totals are accurate.
-ReviewRequestSearchGroupadditionally handles the Contents filter, which
restricts the text query to specific ES fields and optionally runs a parallel
query against comment indexes to surface review requests with matching
comments.
- Also addspopulate_bench_datamanagement command andbench_manager.pyfor
populating and benchmarking persistent datasets at 1k, 10k, 100k, and 1M
scale across Postgres, MySQL, and MariaDB.
Verified that
DisjointFacetEnginebuilds the correct msearch body structure,
enforces the disjoint property on aggregation sub-queries, and produces exactly
one msearch call per search regardless of how many filters are active. Verified
thatFilterBuildergenerates correct Elasticsearch clauses for each filter
type and that the permission filter is always injected. Verified that
FacetedSearchEngineroutes full searches to the active group and count-only
queries to inactive groups.Performance benchmarks were run at 10k, 100k, and 1M review requests on
Postgres, MySQL, and MariaDB. A 6-filter faceted search against a 1M-document
index completes in 4.7ms with latency remaining flat across all scales. Full
results are in the attached benchmark report.