PrestaShop tiene una buena herramienta de búsqueda, pero a veces no se adapta a todas sus necesidades. Además, no es realmente rápida y en tiendas grandes la búsqueda y la indexación podrían ser muy lentas.
Si desea algo mejor, puede usar un gran reemplazo: Sphinx.
De Wikipedia:
Sphinx es un motor de búsqueda de texto completo de código abierto/software libre diseñado para proporcionar funcionalidad de búsqueda de texto completo a aplicaciones cliente.
Sitio web de Sphinx – http://sphinxsearch.com/
Instalación de Sphinx
He usado Debian 8.1. En otras distribuciones de Linux (y especialmente en Windows) la instalación puede diferir ligeramente.
Si Sphinx está disponible en los repositorios, simplemente instálelo:
1 2 3 | su apt-get update apt-get install sphinxsearch |
Si Sphinx no está disponible en los repositorios, puede descargar un instalador del sitio web oficial e instalar las dependencias:
1 2 3 | apt-get install mysql-client unixodbc libpq5 wget http://sphinxsearch.com/files/sphinxsearch_2.2.9-release-1~wheezy_i386.deb dpkg -i sphinxsearch_2.2.9-release-1~wheezy_i386.deb |
Tiene que reemplazar el nombre y la url del instalador con las versiones relevantes actuales. Todas están disponibles en el sitio web oficial.
Configuración de Sphinx
Abra la configuración de Sphinx y edítela:
1 | nano /etc/sphinxsearch/sphinx.conf |
Necesita editar el bloque predeterminado existente «source src1» (o agregar un nuevo bloque). El resultado debería verse así:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | source PrestaSite { type = mysql sql_host = localhost # PrestaShop database username sql_user = DBUSER # PrestaShop database password sql_pass = DBPASSWORD # PrestaShop database name sql_db = DBNAME sql_port = 3306 # optional, default is 3306 sql_query_pre = SET NAMES utf8 # MySQL query with list of fields for indexation sql_query = SELECT id_product, name, description, description_short FROM ps_product_lang } |
Primero puede ver la configuración para conectarse a la base de datos (no olvide cambiarla a la relevante). El parámetro sql_query contiene una consulta con los campos para la indexación.
Estas son todas las configuraciones de mi archivo de configuración. Básicamente, el archivo de configuración está bien documentado y todas las opciones se describen allí, por lo que podría personalizar fácilmente su configuración.
A continuación, en el bloque «index definition» necesita configurar el índice:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | index PrestaSite { # data source for indexation source = PrestaSite # location for index data path = /var/lib/sphinxsearch/data/prestasite # morphology preprocessors morphology = stem_en # minimal word length for indexation min_word_len = 1 } |
A continuación puede ver los bloques «indexer settings» y «searchd settings». Por lo general están bien, puede simplemente omitirlos.
Entonces, hemos configurado la fuente de datos (source PrestaSite) y el índice (index PrestaSite).
Indexación
Inicie el indexador para indexar su base de datos:
1 | indexer --all |
Lanzamiento de Sphinx
No olvide iniciar/reiniciar searchd:
1 | searchd |
Y agregue el indexador a crontab:
1 | 15 * * * * root indexer --all |
La indexación se iniciará cada hora.
Configuración de PrestaShop
A continuación puede ver el código para PrestaShop 1.6. Para otras versiones de PrestaShop puede diferir ligeramente.
Cree (o edite) el override de la clase Search:
/override/classes/Search.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | <?php class Search extends SearchCore { public static function find($id_lang, $expr, $page_number = 1, $page_size = 1, $order_by = 'position', $order_way = 'desc', $ajax = false, $use_cookie = true, Context $context = null) { if (!$context) { $context = Context::getContext(); } $db = Db::getInstance(_PS_USE_SQL_SLAVE_); // TODO : smart page management if ($page_number < 1) $page_number = 1; if ($page_size < 1) $page_size = 1; if (!Validate::isOrderBy($order_by) || !Validate::isOrderWay($order_way)) return false; if (!Validate::isOrderBy($order_by) || !Validate::isOrderWay($order_way)) { return false; } $start = ($page_number - 1) * $page_size; // Sphinx search, get ids of found products $sphinx_results = self::getSphinxResults($expr, $start, $page_size); $result = null; $total = 0; // get products by id if something found if (is_array($sphinx_results) AND sizeof($sphinx_results) AND isset($sphinx_results['total']) AND $sphinx_results['total'] > 0) { $sql = 'SELECT p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, pl.`description_short`, pl.`available_now`, pl.`available_later`, pl.`link_rewrite`, pl.`name`, MAX(image_shop.`id_image`) id_image, il.`legend`, m.`name` manufacturer_name, MAX(product_attribute_shop.`id_product_attribute`) id_product_attribute, DATEDIFF( p.`date_add`, DATE_SUB( NOW(), INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY ) ) > 0 new FROM '._DB_PREFIX_.'product p '.Shop::addSqlAssociation('product', 'p').' INNER JOIN `'._DB_PREFIX_.'product_lang` pl ON ( p.`id_product` = pl.`id_product` AND pl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('pl').' ) LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa ON (p.`id_product` = pa.`id_product`) '.Shop::addSqlAssociation('product_attribute', 'pa', false, 'product_attribute_shop.`default_on` = 1').' '.Product::sqlStock('p', 'product_attribute_shop', false, $context->shop).' LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON m.`id_manufacturer` = p.`id_manufacturer` LEFT JOIN `'._DB_PREFIX_.'image` i ON (i.`id_product` = p.`id_product`)'. Shop::addSqlAssociation('image', 'i', false, 'image_shop.cover=1').' LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (i.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$id_lang.') WHERE p.`id_product` IN('.implode(',', $sphinx_results['results']).') GROUP BY product_shop.id_product'; $result = $db->executeS($sql); // results count $total = $sphinx_results['total']; } if (!$result) { $result_properties = array(); } else { $result_properties = Product::getProductsProperties((int)$id_lang, $result); } return array('total' => $total, 'result' => $result_properties); } protected static function getSphinxResults($search_query, $page_number, $page_size) { $results = array(); $total = 0; if(!$search_query) return null; // connect to Sphinx database $link = mysqli_connect('127.0.0.1', '', '', '', '9306'); if($link) { $query = 'SELECT * FROM `PrestaSite` WHERE MATCH(''.pSQL($search_query).'') limit '.(int)$page_number.', '.(int)$page_size.';'; if ($result = $link->query($query)) { while($query_results = $result->fetch_array()) { $results = array_merge($results, $query_results); } /* clear result */ $result->close(); } // get count of results $query_total = 'SELECT count(*) FROM `PrestaSite` WHERE MATCH(''.pSQL($search_query).'');'; if ($result = $link->query($query_total)) { $total = (int)$result->fetch_array()[0]; if($total > 1000) $total = 1000; } mysqli_close($link); } return array('results' => $results, 'total' => $total); } } |
Básicamente, el código es bastante simple. Sobrescribimos la función «find», en la que reemplazamos la búsqueda de PrestaShop por la búsqueda de Sphinx. Sphinx devuelve los ids de los productos y mediante el uso de esos ids consultamos los datos de los productos. La segunda función (getSphinxResults) realiza directamente la búsqueda.
Al final, necesita borrar la caché y eliminar la caché de clases (/cache/class_index.php). ¡Todo listo!
