Magento: Enhance your search results with Elasticsearch

Magento search results are not very relevant even with the activation of the MySQL Fulltext search. Here is a module that allows you to use Elasticsearch search engine to optimize the search results of your Magento store.

Be careful, this module is for Magento 1.7+ only!

What is Elasticsearch?

Elasticsearch is a very powerful search engine written in Java and based on Apache Lucene. It allows to index millions of documents by replicating data automatically on Elasticsearch nodes you create. He thus manages to make the load distribution. Requests are made in JSON through HTTP requests, which makes it usable with any programming language.

Elasticsearch installation

To install Elasticsearch, simply follows instructions on GitHub: https://github.com/elasticsearch/elasticsearch#installation.

I also recommend installing the plugin elasticsearch-head that will allow you to use Elasticsearch from a web browser.

Installation of Elasticsearch module for Magento 1.7+

Extension is available on GitHub: https://github.com/jreinke/magento-elasticsearch

You have 2 ways to install it:

  1. Manual installation: download package here, unzip in Magento root folder, then clean cache.
  2. Installation with modgit:

    modgit -e README.md clone elasticsearch https://github.com/jreinke/magento-elasticsearch.git

    See a full example of how to use modgit here.

Module configuration

Go to “System > Configuration > Catalog > Catalog Search” :

Now you can configure Elasticsearch parameters as you wish and reindex catalog search.

Elasticsearch documentation is available here.

For the curious, the code that builds and runs the query to Elasticsearch is
here.

48 Responses to “Magento: Enhance your search results with Elasticsearch”

  1. gondo says:

    hi
    out of curiosity, why did you choose elasticsearch over solr?

  2. Herr Jay says:

    Hello,

    Tout d’abord merci pour le travail que tu fournis et que tu fais partager avec la communauté, vraiment cool !

    Je tente d’utiliser ton module, j’ai essayé sur une install propre de magento 1.7.2 avec les samples data de magento.

    Je rencontre une erreur “elasticsearch” à l’indexation, la voici :

    “failed to execute bulk item (index) index {[magento][product][16|1] (…)”

    L’exception JAVA est :

    “java.lang.IllegalArgumentException: Min shingle size must be <= max shingle size"

    Sais tu si ça provient de ton module ou bien de mon installation de ElasticSearch (je suis sous ubuntu), y'a t-il une configuration spécifique d'ElasticSearch ?

    Merci par avance !

    • Johann Reinke says:

      Hello,

      As-tu toujours le problème ?
      Moi j’ai essayé avec le sample data justement sur une 1.7 de Magento et je n’ai pas eu ce bug. Je pense quand même que cela peut venir de mon module et non pas de ta configuration d’ES.

  3. David Pilato says:

    Salut Johann,

    Tu devrais ajouter ta repo par un pull request ici :
    http://www.elasticsearch.org/guide/appendix/clients.html

    @++
    David

  4. Alexander says:

    Hi, super, thanks for this Extension! Support your extension the Ajax Autosuggest function?

  5. Nenad says:

    Hallo Johann,

    Ich habe die Erweiterung manuell installiert, da war nichts unter System / Configuration / Catalog Search in Bezug auf Elasticsearch.
    Bei Module Output wurde einzig das Modul gelistet.

    Habe danach manuell:
    INSERT INTO core_config_data (scope, scope_id, path, value) VALUES(‘default’, 0, ‘catalog/search/engine’, ‘jr_search/engine_elasticsearch’);
    ausgeführt, noch immer nichts mit Elasticsearch und ich kann nun keinen Reindex von “Catalog Search Index” mehr machen:

    MapperParsingException[Analyzer [analyzer_] not found for field [description]]
    Cannot initialize the indexer process.

    Ich nutze Magento CE 1.7.0.2 und Elasticsearch 1.19.11.

    Hast Du vielleicht eine Idee was da falsch läuft?

  6. Laurent says:

    Salut,
    J’ai installé le module avec modgit sans soucis. En revanche, après le vidage du cache j’ai une erreur 503 sur la page de config/catalogue dans l’admin. J’ai cette erreur dans les logs:
    ‘Mage_Core_Exception’ with message ‘Type de bloc non valide : JR_Search_Block_Catalog_Layer_View’
    Vous avez une idée?

    Merci.
    Laurent

  7. Laurent says:

    Problème résolu! J’avais oublié de tout recompiler!
    Merci

  8. Fincom says:

    Bonjour,

    Lors du lancement du processus de réindexation, j’obtiens l’erreur suivante:

    RemoteTransportException[[Zartra][inet[/192.168.0.41:9300]][indices/mapping/put]]; nested: MapperParsingException[Analyzer [analyzer_] not found for field [description]];
    Impossible d’initialiser le process d’indexation.

    C’est le m^me problème rencontré par Nedad, su Magento 1.7.0.2.

    Bien cordialement

  9. Huso says:

    Hello from Germany,

    I have an Question, because the SearchEngine is not working in Frontend…
    What should I write in the Field (Index Name)? It is now Magento and my Store is in the Main Folder on the Server.

    • Johann Reinke says:

      Hi!
      I’m not sure to understand what you ask me exactly. Index name is the name you want to give to your elasticsearch index, it’s similar to the name you give for your mysql database.

  10. Sebastien says:

    Bonjour,

    as-tu des exemples de sites qui utilisent le module ?

    Merci par avance pour ta réponse.

  11. Gergely says:

    Bonjour Johann,

    J’ai essayé ton extension, mais le ‘layered navigation’ sur le frontend a disparu. Qu’est-ce que je fais mal?

    Cordialement,
    Gergely

  12. Brice says:

    Salut,

    Je rencontre le même problème que Gergely, les filtres du layer ne s’affichent pas.
    Après avoir fait une rapide enquête on s’aperçoit que la construction des filtres se fait avant la requête. C’est à dire que lors de l’appel à la méthode “_getItemsData” de chaque filtres la collection n’est pas chargée et par extension le tableau “$this->_facetedData” ne contient pas les facets. Ce tableau est remplie dans le “_beforeLoad” de la collection (ligne 280 de la classe JR_Search_Model_Resource_Catalog_Product_Collection).

    Je n’ai pas encore trouvé de solution fonctionnelle (j’ai tenté un load de la collection dans le “_beforeHmtml” du block JR_Search_Block_Catalogsearch_Layer, j’ai bien les filtres mais je perds la pagination…).

    Quelqu’un a une solution à ce problème ?

    Merci,
    Brice

    PI: j’ai récupérer la dernière version du module Magento. Elastic en version 0.20.6.

    • Brice says:

      Re,

      une autre piste qui confirme un problème d’ordonnancement. Si je déplace le layer dans la colonne de droite (gauche par défaut), celui-ci apparaît bien car la méthode “_getItemsData” est appelé après le “_beforeLoad” de la collection.

      Vraiment étrange… mais toujours pas une solution

      Brice,

      • Johann Reinke says:

        Salut,

        J’ai rencontré ce problème sur un autre projet.
        Tout fonctionne bien avec le thème par défaut de Magento mais pas avec leur thème personnalisé.
        Pour le moment, le seul moyen a été d’ajouter en haut du fichier :

        app/design/frontend/<package>/<theme>/template/catalog/layer/view.phtml

        la ligne suivante :

        $this->getLayer()->getProductCollection()->load();

        Je vais essayer d’investiguer plus longuement pour trouver d’où vient le problème.

        • Brice says:

          Salut,

          Le problème de cette technique c’est que la page de résultats n’est plus correct. Ex : recherche retournant 2288 résultats à raison de 10 résultats par page, et bien j’ai 100 résultats par page (sans doute une limitation côté Elasticsearch ?).
          Tu n’a pas ce problème avec cette technique ?

          Brice,

          • Johann Reinke says:

            Si en effet et on avait dû modifier le comportement de la méthode _getParams() sur la collection.
            J’ai créé un Gist pour expliquer les modifications : https://gist.github.com/jreinke/5364062

            Ce n’est bien évidemment pas normal d’en arriver là mais le problème était complexe, il faut que je creuse ça longuement :-/

  13. Brice says:

    Merci, ça marche nickel.
    Je suis plutôt passer par une surcharge du layer et l’ajout d’un _beforeToHtml dans lequel je vais le load de la collection.

    Brice,

    • Gergely says:

      Merci Johann pour la solution.

      Brice, est-ce que tu peux m’expliquer ce que tu comprends par surcharge du layer et l’ajout d’un _beforeToHtml? Tu peux me donner un example? Ca m’aiderait beaucoup, je ne suis pas encore expert dans Magento, ca fait que quelques mois que j’ai commencé a creuser dans le code, mais j’essaye d’avancer vite.
      Merci d’avance,
      Gergely

  14. Brice says:

    Gergely,

    J’ai tout d’abord créé une classe avec le contenu suivant :

    class MonModule_Elasticsearch_Block_Catalogsearch_Layer extends JR_Search_Block_Catalogsearch_Layer {

    protected function _beforeToHtml() {
    parent::_beforeToHtml();
    if (Mage::helper('jr_search')->isActiveEngine()) {
    $this->getLayer()->getProductCollection()->load();
    }
    return $this;
    }

    }

    On indique ici que si le moteur de recherche est elasticsearch alors on force le chargement de la collection. Cette action est effectué juste avant de rendre le HTML. Je trouve que passer par ce mécanisme correspond plus au standard Magento, plutôt que de le faire directement dans le template. D’ailleurs Magento utilise la même technique dans le _beforeToHtml de la liste de produit.

    Dans le config.xml on déclare, dans la section blocks, la surcharge suivante :

    MonModule_Elasticsearch_Block_Catalogsearch_Layer

    Pour être sûr que notre surcharge passe avant celle du module de Johann, il faut ajouter une dépendance dans la déclaration du tiens :

    true
    local

    En espérant que ça aide.

    Brice,

  15. Brice says:

    Salut,

    Je reviens faire mon casse pied mais il y a un soucis avec le patch proposé (rien de très grave). Le tri ne fonctionne plus… Pour corriger le problème il faut modifier légèrement la méthode _getParams de la collection produit pour récupérer le tri en dans l’URL ou via la toolbar.

    J’ai mis à jour mon Gist avec la classe Collection.php : https://gist.github.com/aya-brice/5403608

    En espérant que ça aide.

    Brice,

  16. Fadel says:

    Bonjour,

    merci pour votre Module.

    après plusieurs modifs pour adapter votre module a mes besoins, et vu que j’ai plus de 2M de produits sur ma base de données l’indexation est devenu un vrais cauchemar ( plus de 2 min ).
    après l’appel à la méthode save() il y a plusieurs type d’indexation qui se déclenchent ( ‘catalog_product_price’, ‘cataloginventory_stock’,’tag_summary’, ‘catalog_product_attribute’, ‘catalog_url’, ‘catalog_product_flat’, ‘catalog_category_flat’, ‘catalog_category_product’, ‘catalogsearch_fulltext’ )

    ma question est la suivante : comment je peut déclenché juste l’indexation Elasticsearch sans passer par les autres.

    merci d’avance.

  17. Otto Smittenaar says:

    Hi Johann,

    Great extension. It is working perfectly with the Sample database but not with our customer databases. The data query’s send to Elasticsearch are incorrect becouse of some data. But we are unable to determine the exact cause.

    Can you help us with this?

    Best regards,

    Otto Smittenaar

  18. Nilesh says:

    hi this is great article. I have used ES in my project but can you help me i want to add category name also in json array result. What i’ll do?

  19. Jeremy Bass says:

    Small question, why elasicsearch over sphinx?

  20. Ovidiu says:

    How to narrow results based on attribute match ?

  21. Manik says:

    Hello,
    i have applied elastic search on my magento website — http://www.myessentials.ca/dev. but its not working. can u help me out on this

    Thanks
    Manik

  22. Alex says:

    Good day,

    story:
    1. I have installed Magento ver. 1.7 with products data already existing
    2. I’ve installed ES on the same CentOS server, ES works well
    3. I’ve installed this magento extension, it appeared in admin part and seems all right
    4. But there is blocker issue – when I try reindex “Catalog Search Index” I’m getting next error

    ElasticSearchIllegalArgumentException[Can't update non dynamic settings[[index.analysis.analyzer.edge_ngram_back.tokenizer, ......................
    ...................................... , index.analysis.filter.edge_ngram_back.min_gram]] for open indices[[magento]]]
    Cannot initialize the indexer process.
    

    question:
    1. please let me know what may be the reason of what so I can pinpoint the issue?

    thank you very much

  23. Alex says:

    >>> updated

    story:
    1. installed clean magento store ver. 1.7 on local pc Fedora19
    2. installed ES + this extension

    result:
    1. exactly the same error happens when edit => save product

    question:
    1. am I doing something wrong? please advise

    thanks again

  24. Alex says:

    >>> updated

    log info regarding my posts above added

    [2013-12-16 19:02:07,459][DEBUG][action.admin.indices.settings] [Deadpool] failed to update settings on indices [magento]
    org.elasticsearch.ElasticSearchIllegalArgumentException: Can't update non dynamic settings[[index.analysis.analyzer.edge_ngram_back.tokenizer, index.analysis.filter.shingle.output_unigrams, index.analysis.analyzer.shingle_strip_apos_and_ws.filter.3, index.analysis.analyzer.shingle_strip_apos_and_ws.filter.2, index.analysis.filter.snowball_en.type, index.analysis.analyzer.shingle_strip_apos_and_ws.filter.4, index.analysis.filter.shingle.type, index.analysis.analyzer.shingle_strip_apos_and_ws.filter.1, index.analysis.filter.strip_whitespaces.type, index.analysis.analyzer.shingle_strip_apos_and_ws.filter.0, index.analysis.filter.edge_ngram_front.min_gram, index.analysis.filter.edge_ngram_back.side, index.analysis.filter.length.min, index.analysis.filter.strip_apostrophes.replacement, index.analysis.filter.strip_whitespaces.pattern, index.analysis.filter.edge_ngram_front.max_gram, index.analysis.analyzer.shingle_strip_ws.tokenizer, index.analysis.analyzer.edge_ngram_front.tokenizer, index.analysis.analyzer.edge_ngram_back.filter.1, index.analysis.analyzer.edge_ngram_back.filter.2, index.analysis.filter.snowball_en.language, index.analysis.analyzer.edge_ngram_back.filter.0, index.analysis.filter.length.type, index.analysis.filter.strip_apostrophes.pattern, index.analysis.analyzer.shingle.filter.2, index.analysis.analyzer.shingle.filter.0, index.analysis.filter.shingle.max_shingle_size, index.analysis.analyzer.shingle.filter.1, index.analysis.filter.edge_ngram_back.max_gram, index.analysis.analyzer.edge_ngram_front.filter.0, index.analysis.analyzer.edge_ngram_front.filter.1, index.analysis.analyzer.edge_ngram_front.filter.2, index.analysis.analyzer.whitespace.tokenizer, index.analysis.analyzer.shingle.tokenizer, index.analysis.analyzer.whitespace.filter.0, index.analysis.analyzer.analyzer_en.type, index.analysis.analyzer.analyzer_en.filter.1, index.analysis.analyzer.analyzer_en.filter.0, index.analysis.analyzer.analyzer_en.filter.2, index.analysis.filter.edge_ngram_front.type, index.analysis.analyzer.shingle_strip_apos_and_ws.tokenizer, index.analysis.filter.strip_apostrophes.type, index.analysis.filter.edge_ngram_back.type, index.analysis.analyzer.shingle_strip_ws.filter.3, index.analysis.analyzer.shingle_strip_ws.filter.2, index.analysis.analyzer.shingle_strip_ws.filter.1, index.analysis.analyzer.shingle_strip_ws.filter.0, index.analysis.filter.strip_whitespaces.replacement, index.analysis.filter.edge_ngram_front.side, index.analysis.analyzer.analyzer_en.tokenizer, index.analysis.filter.edge_ngram_back.min_gram]] for open indices[[magento]]
            at org.elasticsearch.cluster.metadata.MetaDataUpdateSettingsService$2.execute(MetaDataUpdateSettingsService.java:248)
            at org.elasticsearch.cluster.service.InternalClusterService$UpdateTask.run(InternalClusterService.java:298)
            at org.elasticsearch.common.util.concurrent.PrioritizedEsThreadPoolExecutor$TieBreakingPrioritizedRunnable.run(PrioritizedEsThreadPoolExecutor.java:135)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
            at java.lang.Thread.run(Thread.java:744)
    

    any clue? :) thank you

  25. Harry says:

    I am trying to integrate qbox.io with ES and I keep getting this error: ‘Elasticsearch engine is not available.’ Needless to say features like suggestions are not working. Please help. Thanks

  26. Sebastian says:

    Hello,

    I got an error with your extension. It is not possible to reindex,

    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) |
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) |
    at java.lang.Thread.run(Thread.java:744) |
    Caused by: java.lang.NumberFormatException: For input string: “Array” |
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) |
    at java.lang.Integer.parseInt(Integer.java:492) |
    at java.lang.Integer.parseInt(Integer.java:527) |
    at org.elasticsearch.common.xcontent.support.AbstractXContentParser.intValue(AbstractXContentParser.java:126) |
    at org.elasticsearch.index.mapper.core.IntegerFieldMapper.innerParseCreateField(IntegerFieldMapper.java:307) |
    at org.elasticsearch.index.mapper.core.NumberFieldMapper.parseCreateField(NumberFieldMapper.java:215) |
    at org.elasticsearch.index.mapper.core.AbstractFieldMapper.parse(AbstractFieldMapper.java:408) |

    As you can see you have the product entry “ye_material”:["Array","210"] which throws this error (Caused by: java.lang.NumberFormatException: For input string: “Array” )

    Where can I find the error?

    Sebastian

  27. Erik says:

    Hi,

    unfortunately the patch aya brice provided under https://gist.github.com/aya-brice/5403608 is not available anymore. Can someone provide the code again? Help is much appreciated! :)

  28. Alok says:

    You mention this as supporting 1.7+
    Will it work fine on magento 1.9?

  29. neeth says:

    i tried this but didnt work..i mean der is no search engine option in my magento admin area’s system-config-catalog-catalogsearch

    what do u think went wrong?

  30. Ashish says:

    Does the index name we specify in magento configuration also gets created in elastic search server. Once the configuration is complete can we see the index in elastic search server too

  31. lou says:

    Hi, the extension works wonderfully, I have only a question. When I write something on the searchbar and then I hit the enter button, I correctly go to the search result page. In this page, items are ordered by relevance. I already created a custom attribute to order products on list templates. I’d like to use this custom attribute to oder search result as well. So, is there a way to have the search result page ordered by my custom attribute instead of by relevance? thanks

  32. Hi :) I found this plugin to be very attractive and elegant. The carousel implementation looks awesome as well. Can you please tell me how to use this plugin (maybe from the admin part, or somewhere else?) to index the ElasticSearch with some catalog/product/categories data, and then, how can I be able to search this new data with the Search bar (Search textbox) in Magento? Thanks in advance and keep up the great work!

    Vlad

Leave a Reply to Manik

* Required fields

Categories