30 июля 2009 г. MySQL Pyha SMF SphinxSearch Поисковые системы

Легкая замена стандартного поиска в SMF на Sphinx

smf_sphinx

Потребовалась замена на ПыхоФоруме стандартного поиска на Sphinx, а также сделать нормальный поиск по пользователям. Для этого потребовалось установить Sphinx и движок для MySQL - SphinxSE.

Подготавливаем индекс

Пишем Sphinx-source:

source pyha_forum
{
    type = mysql
    sql_host = localhost
    sql_user = pyha
    sql_pass = 
    sql_db = pyha
    sql_port = 3306
    sql_sock = /tmp/mysql.sock

    sql_query_pre = SET NAMES utf8
    sql_query_pre = SET CHARACTER SET utf8

    sql_query = \
        select ID_MSG, concat('user:',posterName) as posterName, subject, body \
        from smf_messages

    sql_query_info = select ID_MSG, posterName, subject, body from smf_messages where ID_MSG = $id
    sql_ranged_throttle = 0
}
Поиск по пользователям реализован за счет "concat('user:',posterName)". И достаточно в поисковую строку ввести "user:adw0rd php", чтобы найти все мои сообщения связанные с php на пыхе.


Пишем Sphinx-index:

index pyha_forum
{
    source = pyha_forum
    path = /var/sphinxsearch/pyha_forum
    docinfo = extern
    mlock = 0
    morphology = stem_enru
    min_word_len = 2
    charset_type = utf-8
    charset_table = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F
    min_infix_len = 2
    enable_star = 1
}

Далее, создаем таблицу для Sphinx'a:

CREATE TABLE `sphinx_smf_messages` (
  `id` int(11) NOT NULL,
  `weight` int(11) NOT NULL,
  `query` varchar(3072) NOT NULL,
  `group_id` int(11) default NULL,
  KEY `query` (`query`(1024))
) ENGINE=SPHINX DEFAULT CHARSET=utf8 CONNECTION='sphinx://localhost:3312/pyha_forum';

Подробнее о SphinxSE: http://adw0rd.ru/2009/mysql-sphinxse/

Меняем код в SMF

В /Source/Search.php (строка ~1377) ищем:

$request = db_query(
   "SELECT " . (empty($search_params['topic']) ? 'lsr.ID_TOPIC' : $search_params['topic'] . ' AS ID_TOPIC') . ", lsr.ID_MSG, lsr.relevance, lsr.num_matches
    FROM ({$db_prefix}log_search_results AS lsr" . ($search_params['sort'] == 'numReplies' ? ", {$db_prefix}topics AS t" : '') . ")
    WHERE ID_SEARCH = " . $_SESSION['search_cache']['ID_SEARCH'] . ($search_params['sort'] == 'numReplies' ? "
        AND t.ID_TOPIC = lsr.ID_TOPIC" : '') . "
    ORDER BY $search_params[sort] $search_params[sort_dir]
    LIMIT " . (int) $_REQUEST['start'] . ", $modSettings[search_results_per_page]", __FILE__, __LINE__);

и заменяем на

$request = db_query(
   "SELECT `sm`.`ID_TOPIC`, `ssm`.`id` AS `ID_MSG`, 1000 AS `relevance`, 0 AS `num_matches`
    FROM `sphinx_smf_messages` AS `ssm` 
    LEFT JOIN `smf_messages` AS `sm`
        ON `ssm`.`id` = `sm`.`ID_MSG`
    WHERE `ssm`.`query` = '".$context['search_params']['search'].";weights=1,2,3'
    LIMIT " . (int) $_REQUEST['start'] . ", $modSettings[search_results_per_page]", __FILE__, __LINE__);

Вот и все, без лишних усложнений мы решили задачу! Если кто знаком с сорцами SMF - то понимает на сколько данное решение оказалось легким ;)

UP[2010-Feb-11]: Обновленная версия поиска:

$searchQuery = preg_replace('/[^[a-z][а-я]\s\d_-]+/iu', ' ', $context['search_params']['search']);
$searchQuery = $searchQuery ? $searchQuery : '*';

$request = db_query(
   "SELECT `sm`.`ID_TOPIC`, `ssm`.`id` AS `ID_MSG`, 1000 AS `relevance`, 0 AS `num_matches`
    FROM `sphinx_smf_messages` AS `ssm` 
    LEFT JOIN `smf_messages` AS `sm`
        ON `ssm`.`id` = `sm`.`ID_MSG`
    WHERE `ssm`.`query` = '".$searchQuery.";index=pyha_forum,pyha_forum_delta;weights=30,20,10,5;offset=".intVal($_REQUEST['start']).
                 ";limit={$modSettings['search_results_per_page']};maxmatches=1000;mode=extended;groupby=day:created;sort=extended:@weight desc, created desc'",
    __FILE__, __LINE__
);

Если вы в недоумении что за "pyha_forum_delta", то читайте Sphinx. Для чего нужны дельта-индексы и как их готовить?

Комментарии

это да, решение и правда пиздец легкое, ибо смф тот еще говнокод ...

угу, может новые версии движков лучше?

лучше-то лучше
но мы апгрейд делать не будем :)

epsyl, ну это понятно :)

вот это решение, а я сидел тупил целыми днями, совсем случайно набрел на блог

Круто, хоть я в этом и не шарю, но буду вникать...

Оставьте свой комментарий

Markdown