Improve Default Joomla Search


- Applies to Joomla 2.5.x +, 3.4.x

What?
So I can't stand the way the default "Search" component in Joomla works. The default is to sort the results by popularity (hits) or by most recently added (depending on your version) which I have never seen in any other system.

I've googled and binged but could not find anything that documents how to bring it into line with other search systems. So here we go, hope this helps you.


Why?
I've created search systems for a plethora of other systems. The aim of this article is to enhance the Joomla search into par with Google and Wikipedia (or near enough).


How?
I'd like to use various techniques, and the first part of this article (Stage 1) is the only part you need to modify as this will improve your Joomla search results by giving priority to articles where the search term is in the article title.

In the stages thereafter, I'm going to simply enhance the relevance factor:
  • Soundex: Built-in function to list matches that sound like the search term.
  • Levenshtein: Allows for typos and matches to words that are 1 or 2 letters mistyped.
  • Grammar: Account for singular/plural, past/present, and noun/adjective/verb forms.
  • Referencing: If this is a search system for a technical database, and there is one specific article you visit a lot, it would be nicer just to type a number like "1234" and this returns that specific article. In the case of Joomla, we'll use the article ID.

Pre-Notes:
This article consists of instructions to hard-code some core files in Joomla. As a precaution, you may want to back up all your website files and its database. Or, if space is limited, you can backup the files I have listed here (the ones we will be modifying):
  1. \plugins\search\content\content.php
  2. \components\com_search\views\search\tmpl\default.xml
  3. \components\com_search\views\search\view.html.php
  4. \language\en-GB\en-GB.com_search.ini
  5. [IfExists] \modules\mod_rokajaxsearch\mod_rokajaxsearch.xml

Stage 1: Add Relevance [Mandatory Stage]
We want to order by more than just popularity and/or date, but also by our own relevance heuristics. The following change would give radically high relevance to articles where the search term is found in the title.
  1. \plugins\search\content\content.php: Insert this between the if ($sContent && $limit > 0){ and before the from part of the query $query->from('#__content AS a');
    copyraw
    switch ($ordering) {
    
    	// BEGIN: joes new ordering option
    	  case 'relevance':
    		$order = 'relevance DESC';
    		break;
    	// END: joes new ordering option
    	
    	case 'oldest':
    		$order = 'a.created ASC';
    		break;
    
    	case 'popular':
    		$order = 'a.hits DESC';
    		break;
    
    	case 'alpha':
    		$order = 'a.title ASC';
    		break;
    
    	case 'category':
    		$order = 'c.title ASC, a.title ASC';
    		$morder = 'a.title ASC';
    		break;
    
    	case 'newest':
    	default:
    		$order = 'a.created DESC';
    		break;
    1.  switch ($ordering) { 
    2.   
    3.      // BEGIN: joes new ordering option 
    4.        case 'relevance': 
    5.          $order = 'relevance DESC'
    6.          break; 
    7.      // END: joes new ordering option 
    8.   
    9.      case 'oldest': 
    10.          $order = 'a.created ASC'
    11.          break; 
    12.   
    13.      case 'popular': 
    14.          $order = 'a.hits DESC'
    15.          break; 
    16.   
    17.      case 'alpha': 
    18.          $order = 'a.title ASC'
    19.          break; 
    20.   
    21.      case 'category': 
    22.          $order = 'c.title ASC, a.title ASC'
    23.          $morder = 'a.title ASC'
    24.          break; 
    25.   
    26.      case 'newest': 
    27.      default: 
    28.          $order = 'a.created DESC'
    29.          break; 
    « Show Me »

  2. [Same file again and optional if your search opts to search archived articles] \plugins\search\content\content.php: Insert this between the if ($sArchived && $limit > 0){ and before the from part of the query $query->from('#__content AS a');
    copyraw
    <field 
                    name="ordering" 
                    type="list"
                    default="relevance"
                    description="COM_SEARCH_ORDERING_DESC"
                    label="COM_SEARCH_ORDERING_LABEL"
            >
                    <option value="newest">COM_SEARCH_NEWEST_FIRST</option>
                    <option value="oldest">COM_SEARCH_OLDEST_FIRST</option>
                    <option value="popular">COM_SEARCH_MOST_POPULAR</option>
                    <option value="alpha">COM_SEARCH_ALPHABETICAL</option>
                    <option value="category">JCATEGORY</option>
                      <option value="relevance">COM_SEARCH_MOST_RELEVANT</option>
            </field>
    1.  <field 
    2.                  name="ordering" 
    3.                  type="list" 
    4.                  default="relevance" 
    5.                  description="COM_SEARCH_ORDERING_DESC" 
    6.                  label="COM_SEARCH_ORDERING_LABEL" 
    7.          > 
    8.                  <option value="newest">COM_SEARCH_NEWEST_FIRST</option> 
    9.                  <option value="oldest">COM_SEARCH_OLDEST_FIRST</option> 
    10.                  <option value="popular">COM_SEARCH_MOST_POPULAR</option> 
    11.                  <option value="alpha">COM_SEARCH_ALPHABETICAL</option> 
    12.                  <option value="category">JCATEGORY</option> 
    13.                    <option value="relevance">COM_SEARCH_MOST_RELEVANT</option> 
    14.          </field> 
    « Show Me »

  3. [Same file again] \plugins\search\content\content.php: Add the option to select by relevance to the CASE order statement:
    copyraw
    // built select lists
    $orders = array();
    $orders[] = JHtml::_('select.option',  'newest', JText::_('COM_SEARCH_NEWEST_FIRST'));
    $orders[] = JHtml::_('select.option',  'oldest', JText::_('COM_SEARCH_OLDEST_FIRST'));
    $orders[] = JHtml::_('select.option',  'popular', JText::_('COM_SEARCH_MOST_POPULAR'));
    $orders[] = JHtml::_('select.option',  'alpha', JText::_('COM_SEARCH_ALPHABETICAL'));
    $orders[] = JHtml::_('select.option',  'category', JText::_('JCATEGORY'));
      $orders[] = JHtml::_('select.option',  'relevance', JText::_('COM_SEARCH_MOST_RELEVANT'));
    1.  // built select lists 
    2.  $orders = array()
    3.  $orders[] = JHtml::_('select.option',  'newest', JText::_('COM_SEARCH_NEWEST_FIRST'))
    4.  $orders[] = JHtml::_('select.option',  'oldest', JText::_('COM_SEARCH_OLDEST_FIRST'))
    5.  $orders[] = JHtml::_('select.option',  'popular', JText::_('COM_SEARCH_MOST_POPULAR'))
    6.  $orders[] = JHtml::_('select.option',  'alpha', JText::_('COM_SEARCH_ALPHABETICAL'))
    7.  $orders[] = JHtml::_('select.option',  'category', JText::_('JCATEGORY'))
    8.    $orders[] = JHtml::_('select.option',  'relevance', JText::_('COM_SEARCH_MOST_RELEVANT'))
    « Show Me »

  4. To add it to the frontend as option in advanced search: OPTION FOR SITE VISITORS \components\com_search\views\search\tmpl\default.xml:
    copyraw
    COM_SEARCH_MOST_POPULAR="Most Popular"
      COM_SEARCH_MOST_RELEVANT="Most Relevant"
    COM_SEARCH_NEWEST_FIRST="Newest First"
    COM_SEARCH_OLDEST_FIRST="Oldest First"
    1.  COM_SEARCH_MOST_POPULAR="Most Popular" 
    2.    COM_SEARCH_MOST_RELEVANT="Most Relevant" 
    3.  COM_SEARCH_NEWEST_FIRST="Newest First" 
    4.  COM_SEARCH_OLDEST_FIRST="Oldest First" 
    « Show Me »

  5. To add it to the frontend as option in advanced search: FUNCTIONALITY \components\com_search\views\search\view.html.php:
    copyraw
    <field name="ordering" type="list" default="newest" label="Ordering">
    	<option value="alpha">Alphabetical</option>
    	<option value="category">Section/Category</option>
    	<option value="newest">Newest first</option>
    	<option value="oldest">Oldest first</option>
    	<option value="popular">Most popular</option>
    	<option value="relevance">Most relevant</option>
    </field>
    1.  <field name="ordering" type="list" default="newest" label="Ordering"> 
    2.      <option value="alpha">Alphabetical</option> 
    3.      <option value="category">Section/Category</option> 
    4.      <option value="newest">Newest first</option> 
    5.      <option value="oldest">Oldest first</option> 
    6.      <option value="popular">Most popular</option> 
    7.      <option value="relevance">Most relevant</option> 
    8.  </field> 
    « Show Me »

  6. To add it to the frontend as option in advanced search: LANGUAGE FILE \language\en-GB\en-GB.com_search.ini:
    copyraw
    <input type="hidden" name="ordering" id="ordering" value="relevance" />
    1.  <input type="hidden" name="ordering" id="ordering" value="relevance" /> 
    « Show Me »


Third-party AJAX Search modules?
  1. To add it to ROKAJAXSEARCH: \modules\mod_rokajaxsearch\mod_rokajaxsearch.xml:
    <field name="ordering" type="list" default="newest" label="Ordering">
    	<option value="alpha">Alphabetical</option>
    	<option value="category">Section/Category</option>
    	<option value="newest">Newest first</option>
    	<option value="oldest">Oldest first</option>
    	<option value="popular">Most popular</option>
    	<option value="relevance">Most relevant</option>
    </field>
    
    « Show Me »

    Don't forget to change the setting in Joomla Admin Panel > Module Manager > RokAjaxSearch > Basic Options > Advanced Search > Ordering (no functionality to add if you followed Stage 1 above)

Lastly and optionally
I add the following to the core joomla search module PHP template so that the first search is based on the above heuristics:
<input type="hidden" name="ordering" id="ordering" value="relevance" />
This needs to be put alongside the other hidden variables in the module, core joomla file is at /modules/mod_search/tmpl/default.php and I put it just before the closing form tag "</form>". Note that if you are using a 3rd-party template which has it's own login module, you will need to find the file specific to that template (eg. /templates/<name_of_template>/html/mod_login/default.php)

Stage 2: More than Title relevance
So I could stop here as Stage 1 substantially improves your Joomla search, but the above files are enough to start adding your own code to make the "relevance" ordering more relevant.

... ok still to come as I'm really happy with what the above already improves!

Download the above modified files.
The following ZIP file contains the default Joomla v3.4.x core files and then a copy with my modifications above. I use this to quickly add the relevance option to clients websites as it should work for all Joomla installations version 3.4.x.

Download demo files

Category: Joomla :: Article: 506

Credit where Credit is Due:


Feel free to copy, redistribute and share this information. All that we ask is that you attribute credit and possibly even a link back to this website as it really helps in our search engine rankings.

Disclaimer: The information on this website is provided without warranty and any content is merely the opinion of the author. Please try to test in development environments prior to adapting them to your production environments. The articles are written in good faith and, at the time of print, are working examples used in a commercial setting.

Thank you for visiting and, as always, we hope this website was of some use to you!

Kind Regards,

Joel Lipman
www.joellipman.com

Related Articles

Joes Revolver Map

Accreditation

Badge - Certified Zoho Creator Associate
Badge - Certified Zoho Creator Associate

Donate & Support

If you like my content, and would like to support this sharing site, feel free to donate using a method below:

Paypal:
Donate to Joel Lipman via PayPal

Bitcoin:
Donate to Joel Lipman with Bitcoin - Valid till 8 May 2022 3QnhmaBX7LQSRsC9hh6Je9rGQKEGNQNfPb
© 2021 Joel Lipman .com. All Rights Reserved.