» Статистика |
Онлайн всего: 1 Гостей: 1 Пользователей: 0 |
|
Главная » 2013 » Март » 2 » 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)
Внимание! Все пути к файлам должны составляться из локальных дисков, а не из виртуальных. Пути должны быть абсолютными
- Скачайте дистрибутив Sphinx
- Распакуйте архив на локальный диск
- Скопируйте файл libmysql.dll (найдите на сервере в файлах установки MySQL) в папку bin
- Создайте в папке bin конфигурационный файл sphinx.conf
- Настройте Sphinx с помощью конфиг-файла, как описано в мануале
- Запустите файл /path/to/sphinx/bin/indexer.exe с параметрами: --config /path/to/sphinx/sphinx.conf --all
- Если все хорошо, то должен создаться индекс (не забудьте про абсолютные пути в конфиге + должны быть созданы папки для логов и файлов индекса)
- Далее запустите файл /path/to/sphinx/bin/searchd.exe с параметрами: --install --config /path/to/sphinx.conf. Эта операция должна создать новую службу под названием «searchd»
- Запустите службу 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>';
Этот код Вы можете немного поправить под свои нужды и сбросить на сервер, чтобы протестировать работоспособность Вашего автономного веб-поиска.
Итог
Сфинкс — очень шустрый автономный поисковый движек. Он очень прост в использовании — это только на первый взгляд он довольно сложный в установке и использовании. Все вопросы жду в комментариях. Удачи.
-
-
-
-
30.05.2010
Ребят, а вот такой вопрос.
Нужно разработать бота, собирающего данные с указанных источников с пост-очисткой от рудиментов.
Данные: источник сбора, товар, цена
Бот должен по таймеру залезать на каждый требуемый ресурс (список ресурсов определяет пользователь), собирать информацию и складывать ее в базу данных в требуемом виде. Информация — это прайс-лист с товарами, в одном прайс-листе может быть от 1000 до 30000 товаров, т.о. речь идет о достаточно большом массиве данных.
Задача бота: собирать информацию с 100-500 ресурсов в день и обновлять данные в БД. Предположительно, сохранять данные можно в SQL
Вариант написания 100 шаблонов — не подходит, нужно более технологичное решение. Шаблоны постоянно могут меняться и решение становится неустойчиво. Речь идет о прототипе мини-поисковой системы с настраиваемыми параметрами поиска и сохранения результатов.
Может ли этот движок помочь в решении подобной задачи?
-
-
-
-
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
-
19.04.2012
Честно говоря не совсем понял Ваш вопрос...
Попробую ответить так, как понял.
У Вас есть источники (source) в Sphinx, и у Вас есть возможность по клиентскому API обратиться к нескольким источникам Сфинкса подав один запрос сразу к перечню индексов (в index указываются источники). Соответственно, Вы получаете один ответ Сфинкса и для вывода данных пользователю у Вас есть два варианта:
1. В ответах Сфинкса поместить какой-то флаг (sql_attr_uint, секция source конфига Sphinx), например. По этому флагу определять из какого источника получены данные и подтянуть недостающее из соотв. БД
2. Хранить в тех же атрибутах значение тех полей, которые Вы выводите пользователю и таким образом полностью избежать обращения к БД.
-
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 |
|
|
|