Мой сайт
Суббота, 14.06.2025, 07:32
» Меню сайта
» Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0
» Форма входа
Главная » 2013 » Март » 2 » Sphinx search engine
19:59
 

Sphinx search engine

Быстро ищем — Sphinx Search Engine

Sphinx Search Engine

Sphinx Search Engine

Привет всем. Вот вырвал кусок времени из своего нынешнего плотного графика работы, чтобы поделиться с Вами довольно интересным материалом об очень быстром и эффективном автономном поисковом движке - Sphinx.

Что такое Sphinx?

Бесплатный поисковый движек, созданный для индексации содержимого баз данных и поиска по созданным индексам. Распространяется по лицензии GNU General Public License v.2. Поддерживает PostgreSQL и MySQL.

Основные фичи

  • Высокая скорость индексации (до 10 мб/с !)
  • Высокая скорость поиска (за 0.1 с. на 2-4 гигабайтном индексе !)
  • Высокая степень масштабируемости
  • Поддержка распределенного поиска
  • Поддерживает поиск по фразам
  • Поддерживает ранжирование фразы по близости, что обеспечивает хорошую релевантность
  • Поддерживает русский и английский стемминг
  • Неограниченное количество полей на документ, вес которых может быть изменен на лету
  • Группировка документов
  • Стоп-слова
  • Разные режимы работы
  • Общий интерфейс XML
  • Клиент на чистом PHP — нет необходимости чего-то компилировать

Установка (под Windows)

Внимание! Все пути к файлам должны составляться из локальных дисков, а не из виртуальных. Пути должны быть абсолютными

  1. Скачайте дистрибутив Sphinx
  2. Распакуйте архив на локальный диск
  3. Скопируйте файл libmysql.dll (найдите на сервере в файлах установки MySQL) в папку bin
  4. Создайте в папке bin конфигурационный файл sphinx.conf
  5. Настройте Sphinx с помощью конфиг-файла, как описано в мануале
  6. Запустите файл /path/to/sphinx/bin/indexer.exe с параметрами: --config /path/to/sphinx/sphinx.conf --all
  7. Если все хорошо, то должен создаться индекс (не забудьте про абсолютные пути в конфиге + должны быть созданы папки для логов и файлов индекса)
  8. Далее запустите файл /path/to/sphinx/bin/searchd.exe с параметрами: --install --config /path/to/sphinx.conf. Эта операция должна создать новую службу под названием «searchd»
  9. Запустите службу searchd

# # Sphinx configuration file # source enterprises { type = mysql sql_host = localhost sql_user = root sql_pass = sql_db = example sql_port = 3306 # optional, default is 3306 sql_query_pre = SET NAMES utf8 sql_query = SELECT realty_enterprises_ru.id, realty_enterprises_ru.id as enterprise_id, 0 as price_id, realty_enterprises_ru.name, realty_enterprises_ru.label, realty_enterprises_ru.address, realty_enterprises_ru.web, realty_enterprises_ru.short_descr,plugin_regions_ru.name as region,realty_legal_forms_ru.name as legal_form_name FROM realty_enterprises_ru, plugin_regions_ru, realty_legal_forms_ru WHERE realty_enterprises_ru.state = 1 AND plugin_regions_ru.id = realty_enterprises_ru.region_id AND realty_legal_forms_ru.id = realty_enterprises_ru.legal_form_id sql_attr_uint = enterprise_id sql_attr_uint = price_id sql_query_info = SELECT * FROM realty_enterprises_ru WHERE id=$id } source infopages { type = mysql sql_host = localhost sql_user = root sql_pass = sql_db = example sql_port = 3306 # optional, default is 3306 sql_query_pre = SET NAMES utf8 sql_query = SELECT id, id as infopage_id, 0 as price_id, enterprise_id, title, body FROM realty_info_pages_ru WHERE state = 1 AND publish = 1 sql_attr_uint = enterprise_id sql_attr_uint = price_id sql_query_info = SELECT * FROM realty_info_pages_ru WHERE id=$id } source pricelists { type = mysql sql_host = localhost sql_user = root sql_pass = sql_db = example sql_port = 3306 # optional, default is 3306 sql_query_pre = SET NAMES utf8 sql_query = SELECT id, id as price_id, enterprise_id, name, body, filename FROM realty_prices_ru WHERE (NOW() BETWEEN created_at AND expired_at) AND state = 1 sql_attr_uint = price_id sql_attr_uint = enterprise_id sql_query_info = SELECT * FROM realty_prices_ru WHERE id=$id } source announcements { type = mysql sql_host = localhost sql_user = root sql_pass = sql_db = example sql_port = 3306 # optional, default is 3306 sql_query_pre = SET NAMES utf8 sql_query = SELECT ann.id, ann.id as announcement_id, ann.text, at.name as type, reg.name as region FROM realty_announcements_ru AS ann,realty_announcements_types_ru AS at, plugin_regions_ru as reg WHERE (NOW() BETWEEN ann.date AND ann.expired_at) AND (ann.state = 1) AND (ann.type_id = at.id) AND (ann.region_id = reg.id) sql_attr_uint = announcement_id sql_query_info = SELECT * FROM realty_announcements_ru WHERE id=$id } index enterprises_index { source = enterprises path = D:\WebServers\usr\local\sphinx\data\enterprises docinfo = extern charset2_type = utf-8 charset2_table = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F morphology = stem_enru enable_star = 1 min_word_len = 3 min_prefix_len = 0 min_infix_len = 3 html_strip = 1 } index infopages_index { source = infopages path = D:\WebServers\usr\local\sphinx\data\infopages docinfo = extern charset2_type = utf-8 charset2_table = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F morphology = stem_enru enable_star = 1 min_word_len = 3 min_prefix_len = 0 min_infix_len = 3 html_strip = 1 } index pricelists_index { source = pricelists path = D:\WebServers\usr\local\sphinx\data\pricelists docinfo = extern charset2_type = utf-8 charset2_table = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F morphology = stem_enru enable_star = 1 min_word_len = 3 min_prefix_len = 0 min_infix_len = 3 html_strip = 1 } index announcements_index { source = announcements path = D:\WebServers\usr\local\sphinx\data\announcements docinfo = extern charset_type = utf-8 charset2_table = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F morphology = stem_enru enable_star = 1 min_word_len = 3 min_prefix_len = 0 min_infix_len = 3 html_strip = 1 } indexer { mem_limit = 64M } searchd { port = 3312 log = D:\WebServers\usr\local\sphinx\log\searchd.log query_log = D:\WebServers\usr\local\sphinx\log\query.log read_timeout = 5 max_children = 30 pid_file = D:\WebServers\usr\local\sphinx\log\searchd.pid max_matches = 1000 seamless_rotate = 0 preopen_indexes = 0 unlink_old = 1 }

Все, установка Sphinx завершена. Рекомендую написать .bat файл для удобства переиндексирования БД. Если возникают проблемы — запустите searchd.exe из командной строки с параметром --config /path/to/sphinx.conf. Все ошибки должны появится тут. Вообще с установкой я очень долго просидел, потому, что таких нюансов, как Вам показываю, не знал, поэтому у Вас должно быть намного меньше трудностей.

Работа со Sphinx

Sphinx имеет свой API. В папке с распакованным дистрибутивом есть папка api. В этой папке Вы можете найти файл sphinxapi.php. Скопируйте данный файл в Ваш проект и подключите его.
Программный интерфейс клиента очень прост и хорошо описан в документации. От себя хочу лишь показать кусочек кода, как пример использования:

<?php require_once 'sphinxapi.php'; $client = new SphinxClient; $client->SetLimits(1,10); // page, count $client->SetArrayResult(true); // возвращать данные массивом /** * Передаем запрос, перечисляем индексы * Получаем специфический массив * Просто сдампите его, чтобы увидеть структуру * */ $result = $client->Query('Авторское право','enterprises_index;infopages_index;pricelists_index'); echo '<pre>'; print_r($result); echo '</pre>';

Этот код Вы можете немного поправить под свои нужды и сбросить на сервер, чтобы протестировать работоспособность Вашего автономного веб-поиска.

Итог

Сфинкс — очень шустрый автономный поисковый движек. Он очень прост в использовании — это только на первый взгляд он довольно сложный в установке и использовании. Все вопросы жду в комментариях. Удачи.

  1. 30.05.2010

    Ребят, а вот такой вопрос.

    Нужно разработать бота, собирающего данные с указанных источников с пост-очисткой от рудиментов.

    Данные: источник сбора, товар, цена

    Бот должен по таймеру залезать на каждый требуемый ресурс (список ресурсов определяет пользователь), собирать информацию и складывать ее в базу данных в требуемом виде. Информация — это прайс-лист с товарами, в одном прайс-листе может быть от 1000 до 30000 товаров, т.о. речь идет о достаточно большом массиве данных.

    Задача бота: собирать информацию с 100-500 ресурсов в день и обновлять данные в БД. Предположительно, сохранять данные можно в SQL

    Вариант написания 100 шаблонов — не подходит, нужно более технологичное решение. Шаблоны постоянно могут меняться и решение становится неустойчиво. Речь идет о прототипе мини-поисковой системы с настраиваемыми параметрами поиска и сохранения результатов.

    Может ли этот движок помочь в решении подобной задачи?

  2. 19.04.2012

    Скажите, а на какой основе Вы выводите результат поиска ? Имею в виду то, что получает пользователь задавая запрос в строке.

    Несколько индексов берутся из нескольких баз данных MySql (пусть даже одинаковых по структуре, на одном сервере, с тем же пользователем).

    Но как вывести результат красиво ?

    У меня получается запрос к ОДНОЙ базе MySQL по результатам отобранным Сфинксом, все в порядке с выводом результата.

    Ну а если этих баз 5-7 ? Мало иметь хороший индекс Сфинкса :) там-то он найдет данные по всем 5-7.

    А вот как вывести результат по 5-7 базам ? в коде прописывать на каждую базу стандарт

    // CONNECT WITH MYSQL mysql_connect('localhost', 'USER', 'passw'); mysql_select_db('a01'); mysql_connect('localhost', 'USER', 'passw'); mysql_select_db('a02');

    и тд — подключаем базу а03, а04...?

    есть ли более прямой или более умный :) способ ?

    С уважением, Serge

  3. 19.04.2012

    Честно говоря не совсем понял Ваш вопрос...

    Попробую ответить так, как понял.

    У Вас есть источники (source) в Sphinx, и у Вас есть возможность по клиентскому API обратиться к нескольким источникам Сфинкса подав один запрос сразу к перечню индексов (в index указываются источники). Соответственно, Вы получаете один ответ Сфинкса и для вывода данных пользователю у Вас есть два варианта:

    1. В ответах Сфинкса поместить какой-то флаг (sql_attr_uint, секция source конфига Sphinx), например. По этому флагу определять из какого источника получены данные и подтянуть недостающее из соотв. БД

    2. Хранить в тех же атрибутах значение тех полей, которые Вы выводите пользователю и таким образом полностью избежать обращения к БД.

  4. 19.04.2012

    Благодарю за намек в какую сторону идти :)
    Если можно, опубликую часть кода чтобы было предметнее...
    //...с началом понятно, далее :

    // (* результат — все индексы)
    $result = $sphinx->Query ($string, '*');

    // Если он есть то...
    if ($result && isset ($result['matches']))

    {
    ...до этого момента все хорошо — но вот далее не могу разобраться.

    Возьму Ваш способ номер 1 (поскольку заранее заданные значения полей меня смущают по логике...говоря простым языком если я задал sql_attr_name = KIEV — значит везде в результатах где выведен «sql_attr_name =» я и буду всегда видеть слово KIEV...так ? а это переменная в зависимости от значения конкретного поля в БД что дал поиск Сфинкса — то есть все же реальные данные надо подтягивать из MySQL). Правильно понимаю ?

    Правда не совсем понимаю как можно «подтянуть недостающее звено из соответствующей БД» (и тем более звенья из 10 БД) не указывая нигде в скрипте опять-таки привычные
    mysql_connect ('localhost', 'USER', 'passw');
    mysql_select_db ('a01'); и тд...а02, а03...
    Надеюсь есть в Сфинксе такое скрытое колдунство...

    ПРИМЕР — СФИНКС проиндексировал 5 баз данных MySQL по 4 полям
    id, name, content, tags
    Предположим я указал в конфиге флаги (могу ведь произвольно добавлять ?)
    sql_attr_name = name
    sql_attr_content = content
    sql_attr_tags = tags

    // Выводим массив
    $ids = array_keys ($result['matches']);

    И что далее написать чтобы

    1) установить кодировку НЕ средствами MySQL как ниже
    // SET CODING
    mysql_query ('SET NAMES utf8');
    mysql_query ('SET CHARACTER SET utf8');


    2) отсортировать результат по релевантности (не обращаясь к MySQL за параметрами) ?
    Для одной (!) базы MySQL это было бы
    $id_list = implode (',', $ids);
    $sql = sprintf ('SELECT * FROM `products` WHERE`id` IN (%s) ORDER BY FIELD (`id`, %s)', $id_list, $id_list);
    $resource = mysql_query ($sql);

    3) вывести результаты поиска в обычный вид для пользователя — ИСПОЛЬЗУЯ ФЛАГИ как Вы советуете
    Опять же для одной базы MySQL это работает как
    echo '<ol>';
    while ($result = mysql_fetch_assoc ($resource)) {
    echo '<li><span><a href="&"quot;http://yoursite.com/'.$result['group_id'].'/?p='.$result['id'].'">'.$result['name'].'</a></span><div>'.mb_substr (htmlspecialchars ($result['description']), 0, 200).'</div>';
    }
    echo '</ol>';

    В результате имеем — NAME как гиперлинк на страницу + описание краткое, уже минимум выполнен.

    Но что именно и как тут заменить на флаги ?

    Чувствую что истина где-то совсем рядом :) мне бы увидеть небольшой пример реального кода чтобы дошло окончательно...уверен что не только мне такое интересно.
    Статей про сам индекс гораздо больше чем про описания КАК выводить результат используя те же флаги конфига...тем более не коннектясь к 10 БД одновременно.
    Даже немножечко, чайная ложечка это уже хорошо !
    Заранее признателен !

Просмотров: 402 | Добавил: sonful | Рейтинг: 0.0/0
Всего комментариев: 0
» Поиск
» Календарь
«  Март 2013  »
Пн Вт Ср Чт Пт Сб Вс
    123
45678910
11121314151617
18192021222324
25262728293031
» Архив записей
» Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Copyright MyCorp © 2025Бесплатный хостинг uCoz