Skip to content

fix(search): add keyword boost support for post search#4329

Open
faisalahammad wants to merge 1 commit into
10up:developfrom
faisalahammad:fix/3534-keyword-boosts
Open

fix(search): add keyword boost support for post search#4329
faisalahammad wants to merge 1 commit into
10up:developfrom
faisalahammad:fix/3534-keyword-boosts

Conversation

@faisalahammad

Copy link
Copy Markdown

Summary

This PR adds the ability to boost specific keywords in post search results. Admins can configure keyword:boost pairs in the Post Search feature settings, and the plugin injects additional multi_match should clauses into the Elasticsearch query, increasing the relevance score for documents that contain those keywords. No reindex is required because the change only affects the query DSL at search time.

Fixes #3534

Changes

Search feature settings (includes/classes/Feature/Search/Search.php)

Before:

There was no UI or mechanism to assign a boost factor to specific keywords.

After:

A new keyword_boosts textarea is exposed in the Post Search feature schema. The dashboard renders it automatically, and submitted values are sanitized into normalized keyword:boost lines.

[
    \x27default\x27 => \x27\x27,
    \x27help\x27    => __( \x27Boost specific keywords in search results. Enter one keyword per line, followed by a colon and a boost number, e.g. <code>premium:5</code>. Boosts must be between 0.01 and 100.\x27, \x27elasticpress\x27 ),
    \x27key\x27     => \x27keyword_boosts\x27,
    \x27label\x27   => __( \x27Keyword boosts\x27, \x27elasticpress\x27 ),
    \x27type\x27    => \x27textarea\x27,
],

Why: The React dashboard is schema-driven, so adding a textarea entry to the feature settings schema is enough to expose the option without touching any JavaScript.

Query injection (includes/classes/Feature/Search/Search.php)

After:

A new apply_keyword_boosts() method hooks into ep_formatted_args at priority 25, after date decay (11) and weighting (20). It appends one multi_match phrase clause per configured keyword to the existing bool.should array, reusing the same search fields so field weights remain effective.

foreach ( $boosts as $keyword => $boost ) {
    $query[\x27bool\x27][\x27should\x27][] = array(
        \x27multi_match\x27 => array(
            \x27query\x27  => $keyword,
            \x27type\x27   => \x27phrase\x27,
            \x27fields\x27 => $search_fields,
            \x27boost\x27  => (float) $boost,
        ),
    );
}

Why: The additional should clauses are added inside the function_score query, so they work together with date decay and per-field weighting. Wrapping the original query in must for the edge case where bool.should is missing keeps the original query required while the keyword clauses remain optional scoring signals.

Filter hook

After:

return apply_filters( \x27ep_search_keyword_boosts\x27, $boosts );

Why: Developers can programmatically override or extend the keyword list without editing the admin setting.

Tests (tests/php/features/TestSearch.php)

After:

Five new tests verify the feature:

  • testKeywordBoostsInjectedWithDecay — confirms two keyword clauses are injected when date decay is enabled.
  • testKeywordBoostsInjectedWithoutDecay — confirms injection when date decay is disabled.
  • testKeywordBoostsNotInjectedWhenEmpty — confirms no extra clauses when the setting is empty.
  • testKeywordBoostsSanitization — confirms malformed lines and out-of-range boosts are dropped.
  • testKeywordBoostsFilter — confirms the ep_search_keyword_boosts filter works.

Why: The tests assert the exact ES query shape and the sanitize behavior, which matches the existing Search/Weighting test patterns in the repo.

Testing

Test 1: Keyword boost affects ranking

  1. Enable Post Search and save keyword_boosts with premium:5.
  2. Create two posts containing the term "product"; one titled "Premium product" and one titled "Regular product".
  3. Search for "product" on the frontend.
    Result: "Premium product" ranks higher than "Regular product".

Test 2: Sanitization

  1. Enter premium:5, sale:0, big:101, negative:-3, and no-colon on separate lines.
  2. Save the settings.
    Result: Only premium:5 is stored; invalid lines are dropped.

Test 3: Empty setting

  1. Leave the Keyword boosts textarea empty and save.
  2. Search for any term.
    Result: The Elasticsearch query shape is unchanged from the default behavior.

Test 4: Filter override

  1. Add a filter on ep_search_keyword_boosts returning array( \x27filterterm\x27 => 7 ).
  2. Run a search.
    Result: The query contains a multi_match clause for filterterm with boost: 7.

Automated tests

vendor/bin/phpunit --filter testKeywordBoosts -c single-site.xml.dist

All five new keyword-boost tests pass. The full TestSearch suite has one pre-existing failure (testSearchOn) that also fails on the upstream develop branch in this environment and is unrelated to this change.

- Add keyword_boosts setting to the Search feature schema.
- Parse and sanitize keyword:boost pairs from admin textarea.
- Inject boosted multi_match should clauses via ep_formatted_args at priority 25.
- Add ep_search_keyword_boosts filter for programmatic overrides.
- Add PHPUnit tests for injection, sanitization, and filter.

Fixes 10up#3534
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.

Enhancement: Add ability to boost specific keywords

1 participant