The new 3.0.0 version of the plugin is available on GitHub and I have submitted it for review for the plugins section here.
This is a BIG update that brings new features and substantial improvements to previous versions:
- Code almost entirely rewritten – no more slow searches or out of memory errors!
- New search and rank logic, a combination of MySQL Full-Text search with Query Expansion and LIKE/REGEXP queries
- New, additional search results page with sortable product list and infinite scroll
- New admin settings, including control of which fields to search and their order
- More robust dropdown auto-positioning
- Support for Zen Cart 1.5.8 language files and plugin upgrade functionality
- Additional template files for the Bootstrap theme
- Integration with Search Log plugin
- Admin settings validation
- Removed jQuery dependency
- Bug fixes
It's compatible with ZC 157 and 158, and PHP version 7.4 through 8.2. There are no modifications to ZC core files.
Highly recommended to read the included HTML readme, not only for the installation instructions but also for additional useful information within.
I report here some of the FAQs included in the readme:
What's the difference between Instant Search and the Advanced Search included in Zen Cart?
Instant Search uses Ajax (no page reload) and searches for matches only on specific fields (product's name, model and description) with the goal of being fast and relevant. It does not load all results at once, but rather stops once it has found enough, and sorts them by relevance to the user query. It can also find similar results (Query Expansion).
The storefront (formerly "Advanced") Search doesn't use Ajax and aims for completeness and flexibility. The user can apply various filter conditions, such as limiting the search to certain categories or price ranges and using AND/OR in the query. It is therefore the tool to use for tailored searches on all available fields. The storefront Search also shows the exact total number of results, but in order to do this and provide pagination, it must first retrieve them all from the database. Additionally, it does not sort the results by relevance.
What's the difference between Instant Search and the Ajax Search of the Bootstrap template?
Aside from a visual difference (Bootstrap Ajax search shows results in a modal instead of a dropdown), both use Ajax (no page reload) and only look for matches on specific product fields (product's name and model, also product's description – if enabled – in the case of Instant Search).
The difference is that Bootstrap Ajax Search is still partially based on the storefront Search algorithm. It retrieves all the results first to count them, and it doesn't sort them by relevance. Compared to the storefront Search though, it's very fast.
Depending on your needs, if you're using the Bootstrap template you may prefer the Bootstrap Ajax Search to Instant Search. You can easily switch between them in the configuration settings.
The search is slow
Ideally, the results should be returned in less than 1 second.
If that's not the case, disable the search in product descriptions (i.e. in the admin Fields to Search and Order setting, use name instead of name-description).
If the search is still slow, disable Query Expansion.
The autocomplete dropdown does not appear
If you have enabled dropdown results and nothing happens when the user types, you may be using a custom template and your search entry boxes have a different CSS selector. You can set the CSS selector in the admin Dropdown - Input Box Selector setting.
The look of the results listing page doesn't fit my store template
The plugin provides template files for Responsive Classic and Bootstrap templates. If you're using a different template, you might need to customize these files to fit your store's theme:
/includes/modules/YOUR_TEMPLATE/product_listing_instant_search.php
/includes/templates/YOUR_TEMPLATE/templates/tpl_instant_search_result_default.php
/includes/templates/YOUR_TEMPLATE/templates/tpl_ajax_instant_search_results_listing.php
The search returns too many non-relevant results
Disable Query Expansion.
The results listing page is slow when a sort is applied
A custom sort (e.g. sort by price) in the product list basically negates the speed advantage of Instant Search, because it has to find and load all products first in order to sort them.
Finally, some more "technical" considerations that led me to rewrite the plugin almost entirely.
The first step of a search is always to break down the search query entered by the user into tokens (separated by spaces) and then search the database for them. Using REGEXP (aka RLIKE) token1|token2|... or using (LIKE %token1% OR LIKE %token2% OR...) doesn't actually change much, execution times are comparable even with a very large number of records (I tried). Reading online, there are instances where one seems to work better than the other, but in general it doesn't make much difference. Nowadays db engines are usually smart enough to use indexes when they need it and do different optimizations to the query on their own.
What really makes the difference in terms of execution time is the sorting of the result according to relevance to the user's query. And here is the sore point.
Loading all the results into memory and then sorting them is a bad idea no matter what (see out of memory errors of the previous versions). Finding and sorting things in the database using indexes will of course always be more efficient. The query_factory class (the class of the global $db object) is also not the best in terms of performance. Using a PDO connection seems better (I tried for example with the DB facade provided by Laravel capsule, now that it's included in ZC 1.5.8), but still: loading and sorting result in memory = very bad idea.
Also, the plugin's custom rating function that I wrote was extremely basic and questionable, to say the least.
There's no need to reinvent the wheel: MySQL already provides a great search and sorting tool, the Full-Text search. It's actually nothing really new, in fact I even used, among others, the same technique described in this famous 13-year-old post that still applies perfectly today (product names have higher priority than product descriptions in search results).
The plugin now creates two full-text indexes (product name and product description) on the product_description table and takes advantage of MySQL Full-Text search function, in combination with some LIKE/REGEXP queries to cover all cases. From what I've tested so far, the performance is good. Searching in product descriptions could obviously lead to longer search times, in which case you should disable the option as explained in the readme.
Full-Text search also comes with the nice optional Query Expansion feature, which can provide similar products to display in the results. More about this in the readme.
Obviously all this is not comparable to the use of a specialized search engine (algolia, elasticsearch and the like), which offers unbeatable performance and many more features (among many, the "did you mean?" feature). But all things considered I think it's still a pretty good result, obtained without the need of install or configure anything else.