Search result ordering by relevance: title > description > keywords

  • Posts: 269
  • Thank you received: 37
  • Hikaserial Subscription Hikashop Business
6 hours 47 minutes ago #371809

-- HikaShop version -- : 6.3.0
-- Joomla version -- : 5.4.4
-- PHP version -- : 8.2
-- Browser(s) name and version -- : Google chrome

Hi,

I'm trying to prioritize search results so that products matching the search term in the "product_name" appear before those matching in the
"description" or "keywords".

Currently, when a customer searches for a word that appears in both a product title and another product's description, the description match sometimes shows up first. I'd like to enforce this ordering:
1. Title match → highest priority
2. Description match → medium priority
3. Keywords match → lowest priority

I've been looking at the `onBeforeProductListingLoad(&$filters, &$order, &$view, &$select, &$select2, &$a, &$b, &$on)` event, and my approach is to inject a relevance score into `$select2` using a `CASE WHEN` expression, then override `$order` with that score:

$scoreExpr = "
    (
        CASE WHEN {$b}.product_name LIKE '%{$term}%' THEN 3 ELSE 0 END
        + CASE WHEN {$b}.product_description LIKE '%{$term}%' THEN 2 ELSE 0 END
        + CASE WHEN {$b}.product_meta_keywords LIKE '%{$term}%' THEN 1 ELSE 0 END
    )
";
$select2 .= ', ' . $scoreExpr . ' AS hika_search_score';
$order = ' hika_search_score DESC, ' . $b . '.product_name ASC';

My concern is: does HikaShop override the `$order` variable after this event fires? In other words, is modifying `$order` inside `onBeforeProductListingLoad` guaranteed to affect the final SQL query, or does the core overwrite it later in the execution flow?

If this approach is not reliable, what would be the recommended way to achieve relevance-based search ordering in HikaShop?

Thank you!

Please Log in or Create an account to join the conversation.

  • Posts: 85571
  • Thank you received: 14003
  • MODERATOR
12 minutes ago #371813

Hi,

Before going into the implementation, I should ask first which search system you are using on your site, because the answer changes quite a lot:

1) Joomla Smart Search (com_finder, the global search component): the onBeforeProductListingLoad event will not fire at all in that case, because Smart Search uses its own controller and query, not HikaShop's product listing view. To bias title > description > keywords there, you would tune the field weights of the HikaShop Smart Search adapter (plg_finder_hikashop), not modify a HikaShop hook. So that would basically require making a copy of the plg_finder_hikashop plugin to set these.

2) HikaShop's own filter system (a search filter on a products listing page): the hook fires AFTER the filter system has already applied its WHERE clauses and possibly its own ORDER BY (in front/views/product/view.html.php, which is upstream of the event). Your override of $order would win, but you would have to extract the term yourself from the request, and you would also be paying for two LIKE evaluations per row (the filter's and yours).

3) A custom search module or form that posts to the HikaShop listing page with the term as a request parameter: this is the scenario where your hook code would work. In that case, your approach is sound, with a couple of fixes:

- $order arrives at the event already including the "ORDER BY" prefix (built as " ORDER BY ".implode(...)). Your line:

$order = ' hika_search_score DESC, ' . $b . '.product_name ASC';

will produce invalid SQL. Use:

$order = ' ORDER BY hika_search_score DESC, ' . $b . '.product_name ASC';

- $term must be escaped to avoid SQL injection. Use $database->escape($term, true) inside the LIKE pattern.

- $select2 is concatenated directly into the SELECT, so your "AS hika_search_score" column is available for the ORDER BY. The hook is honored and $order is not overwritten afterwards.

Please Log in or Create an account to join the conversation.

Time to create page: 0.055 seconds
Powered by Kunena Forum