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

Comments

Not rated
christophe
1
christophe
9 years ago
I added this functionnality to my website, but there is some problems. The most important is that the joomla search engine add '%' to the word. EG : %joel%
So, you have to delete all the % if you want the word be take in account. :
You have to replace every '.
$sql_keyword.'
by
(TRIM(BOTH "%" FROM '.$sql_keyword.'))

With that, it's working very well !
Like Like
Reply | Reply with quote | Quote
Bobby Etheredge
0
Bobby Etheredge
9 years ago
Is there a way to make the search browse the navigation menu titles? I have iframes that are dynamically generated from converted word.doc that are part of a 5th child navigation menu...
Like Like
Reply | Reply with quote | Quote
Bobby Etheredge
0
Bobby Etheredge
9 years ago
Saraeee - I returned the same blank page:
On stage 1:a - there is a typo $sql_keyword. - change to: $.sql_keyword.
Like Like
Reply | Reply with quote | Quote
Saraee
0
Saraee
9 years ago
Thank you dear Joel. With demo files at the end of the article I could do so.
Like Like
Reply | Reply with quote | Quote
Saraeee
0
Saraeee
10 years ago
I did what you explained on my joomla 3 website but had error and no result shown.
Any idea?
Like Like
Reply | Reply with quote | Quote
pankaj
1
pankaj
12 years ago
what to do for titel name search? done all the changes according to u .but the the no sultion for the titel search. if the the article is new it will shown.but if it is old date article then the result is shown in differnt article body in there content. :cry: :cry:
Like Like
Reply | Reply with quote | Quote

Add comment

Your rating:

Submit

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: Please note that the information provided on this website is intended for informational purposes only and does not represent a warranty. The opinions expressed are those of the author only. We recommend testing any solutions in a development environment before implementing them in production. The articles are based on our good faith efforts and were current at the time of writing, reflecting our practical experience 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

Accreditation

Badge - Zoho Creator Certified Developer Associate
Badge - Zoho Deluge Certified Developer
Badge - Certified Zoho CRM Developer

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 bc1qf6elrdxc968h0k673l2djc9wrpazhqtxw8qqp4

Ethereum:
Donate to Joel Lipman with Ethereum 0xb038962F3809b425D661EF5D22294Cf45E02FebF

Please publish modules in offcanvas position.