Использование Sphinx в сложных задачах поиска

    Использование Sphinx в сложных задачах поиска

    Sphinx – это поисковый сервер / движок. Sphinx предназначен для практически всех поисковых задач. Он может искать по тексту по релевантности, умеет искать склоняемые слова («котят» – «котята»), масштабируется горизонтально и имеет удобный интерфейс. Мне недавно пришлось изучить данный комбайн для одной весьма специфической задачи.

    Постановка задачи

    котят часто продают...

    На самом деле, в проекте много сложных для объяснения вещей (не совсем полное техническое задание занимает под 500 страниц 12-м шрифтом), но в сильно упрощённом виде всё выглядит следующим образом:

    Имеется Classified система - система с объявлениями различных категорий. У всех объявлений одной категории имеется определённый набор полей различных типов. Набор полей изменяется из административной панели.

    Например, для объявлений раздела “Авто - Легковые авто” у нас имеется следующий набор полей:

    • Марка
    • Модель
    • Тип кузова
    • ...

    Для объявлений раздела “Недвижимость - Квартиры - Продажа” поля такие:

    • Область
    • Город
    • Район
    • ...

    Необходимо реализовать все возможные операции над объявлениями и, самое главное, их поиск.

    Почему именно Sphinx?

    Без Sphinx тут только костыли...

    Я много, много думал и нашел всего 2 варианта хранения значения полей - сериализованные данные (JSON / XML / ...) в общей таблице объявлений или “кучка таблиц”. На первых порах, когда мы затевали этот проект, я не нашел ни одного варианта полноценного поиска по сериализованным данным (возможно, я просто плохо искал) и нам пришлось реализовывать “костыльный” вариант №2 - создавать по таблице значений для каждой категории, но с появлением в Sphinx (с версии 2.2.x) возможности поиска по JSON столбцам решено было перевести поиск на Sphinx.

    Кроме того, у Sphinx есть определённые преимущества:

    • Sphinx быстрый и стабильный.
    • Sphinx лёгкий в освоении. Официально рекомендуемым протоколом работы со Sphinx есть SphinxQL - протокол на базе SQL. Полнотекстовый поиск, поиск по JSON и даже манипуляции с RealTime индексами не составляют особого труда тем, кто уже знает SQL.
    • Sphinx масштабируемый. Если в процессе роста проекта, загруженность поискового сервера будет подходить к пиковой - вы спокойно можете поднять поисковый кластер из нескольких машин и распределить нагрузку.
    • Sphinx популярный. Следовательно, в сети полно документации, проект постоянно развивается и его уверенно можно использовать в коммерческих продуктах.
    • Sphinx кроссплатформенный. У нас машины разработчиков работают, в основном, на Windows, а на сервере установлен Debian. Однако подобный “зоопарк” по зубам нашему монстру.

    Итак, решено - будем использовать Sphinx. Так с чего же начать?

    Установка Sphinx на Debian

    В репозиториях Debian версии Sphinx обновляются достаточно редко, поэтому нам придётся устанавливать пакет вручную.

    Шаг 1. Качаем отсюдава (http://sphinxsearch.com/downloads/release/). необходимый нам пакет.

    Шаг 2. Устанавливаем библиотеки, необходимые для Sphinx:

    $ sudo apt-get install mysql-client unixodbc libpq5

    Шаг 3. Устанавливаем Sphinx из скачанного .deb пакета:

    $ sudo dpkg -i sphinxsearch_2.3.1-beta-0ubuntu11~trusty_amd64.deb

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

    Настройка Sphinx

    Все настройи хранятся в файле sphinx.conf.

    Исходная таблица

    Я сильно упростил таблицу

    Получение исходных данных

    Конфигурация обычно начинается с секций source. Эти секции описывают данные, которые мы будем тянуть с SQL сервера.

    Тут мы описываем тип подключения (mysql), параметры подключения, SQL запросы (самый главный - sql_query - для выборки данных).

    Поскольку у нас нет необходимости искать по удалённым или неактуальным объявлениям - мы их попросту не будем вносить в индекс, чем убъём двух зайцев сразу - не будем перегружать индекс лишними данными и упростим поисковый запрос.

    1. source src_classified_offers{
    2.     type   		 = mysql
    3.     sql_host   	 = 127.0.0.1
    4.     sql_user   	 = *******
    5.     sql_pass   	 = *******
    6.     sql_db   	 = classified_test
    7.     sql_port   	 = 3306    # optional, default is 3306
    8.     #pre-query
    9.     sql_query_pre   	 = SET NAMES utf8
    10.     # main document fetch query
    11.     sql_query   	 = \
    12.    	 SELECT `id`,`catid`,`vals`, \
    13.    	 `price`,`currency`, \
    14.    	 `name`,`description`, \
    15.    	 UNIX_TIMESTAMP(`published_from`) as published_from_ts \
    16.    	 FROM classified_ads \
    17.    	 WHERE ((`published`=1)AND(`id`>=$start)AND(`id`<=$end))
    18.  
    19.     sql_query_range   	 = SELECT MIN(id),MAX(id) FROM classified_ads
    20.     sql_range_step   	 = 1000
    21.     sql_attr_uint   	 = catid
    22.     sql_attr_json   	 = vals
    23.     sql_attr_float   	 = price
    24.     sql_attr_uint   	 = currency
    25.     sql_attr_timestamp    = published_from_ts    
    26.     sql_ranged_throttle    = 0
    27.     }

    Параметры sql_query_range, sql_range_step и sql_ranged_throttle описывают “выборку частями” из нашей таблицы. Поскольку таблица будет большая, теоретически (в процессе выборки большого количества данных) нас может выбить по таймауту. Запросы частями решают данную проблему.

    Как видите, в конце секции source, идёт описание типов некоторых полей. Например, sql_attr_json - это значения наших полей. Все неописанные поля добавляются в полнотекстовый индекс.

    Выбор типа индекса

    Далее нам необходимо создать секцию индекса. В Sphinx есть 2 типа индекса - обычный и realtime. Давайте выберем обычный индекс. Он проще в обслуживании и более производительный (минус - обновляется с запаздыванием).

    1. index classified_offers{
    2.     source   		 = src_classified_offers
    3.     path   		 = /data/sphinx/classified_offers/
    4.     docinfo   		 = extern
    5.     dict   		 = keywords
    6.     mlock   		 = 0
    7.     morphology   	 = stem_enru
    8.     min_word_len   	 = 1
    9.     html_strip   	 = 0
    10.     }

    Стоит отметить, что директория path должна существовать на момент запуска демона.

    Запуск Sphinx и поиск

    Перед стартом сервиса нам необходимо проиндексировать данные. При изменении структуры (добавили столбец в индекс или поменялся тип) необходимо вначале остановить сервис, а затем запускать полное индексирование командой:

    1. $ sudo service sphinxsearch stop
    2. $ indexer --all

    Затем запускаем демон:

    1. $ sudo service sphinxsearch start

    Если ничего не изменилось - просто вызываем переиндексацию данных без остановки сервиса. Данную команду следует запихнуть в cron для поддержания валидных данных:

    1. $ indexer --all --rotate

    Подключение к серверу Sphinx в PHP (мы используем протокол SphinxQL) ничем не отличается от SQL. Вот только порт придётся использовать нестандартный (обычно 9306).

    Для поиска по JSON указываем поле через точку. Например:

    1. SELECT values.fuel_type from classified_ads where (values.fuel_type=4);

    Для полнотекстового поиска используется ключевое слово MATCH:

    1. SELECT * FROM classified_ads WHERE MATCH('my document');

    Вот и всего-то.

    Комментарии

    27.09.2019 06:32:15
    Avatar of ScottglitaScottglita
    スーパーコピーブランド専門店
    https://www.007kopi.com/product/4739.html

    ルイヴィトン、シャネル、エルメス、ルチェ&ガッバ―ナ、
    バレンシアガ、ボッテガ ヴェネタ、ミュウミュウ、クリスチャンディオール
    その他の偽物バッグコピー、偽物財布コピー、偽物時計コピー、偽物ベルトコピー、偽物指輪コピー、偽物キーケース、商品は全く写真の通りです。
    高級腕時計(N級品),スーパーコピー時計(N級品),財布(N級品)バッグ(N級品),靴(N品),指輪(N級品),ベルト(N級品),マフラー (N級品)
    人気の売れ筋商品を多数取り揃えております。
    全て激安特価でご提供.お願いします.
    ★100%品質保証!満足保障!リピーター率100%!
    ★商品数も大幅に増え、品質も大自信です。
    ★スタイルが多い、品質がよい、価格が低い!
    ★顧客は至上 誠実 信用。
    ★歓迎光臨
    ★送料無料(日本全国)
    ホームページ上でのご注文は24時間受け付けております
    https://www.007kopi.com/product/7098.html
    04.10.2019 02:32:02
    Avatar of ImplerImpler
    Перевозка грузов из Китая по выгодным тарифам!

    Доставку грузов осуществляем всеми видами транспорта в контейнерах.
    Работаем с морскими линиями MAERSK, FESCO, CMA-CGM, APL, SASCO, MSC.
    Отправку контейнерных грузов осуществляем ежедневно,
    Отправку сборных грузов из Китая осуществляем 3 раза в неделю.
    Расчет с поставщиками товаров производим в USD, EUR, CNY, по ставке 1,5% от суммы оплаты.
    Отгрузку товара в РФ осуществляем как полную так и частичную (склад - не виртуальный), комплект документов +НДС.
    Работаем через морские порты ВМТП, ВМКТ, Восточный порт.

    Эл.почта: edem@vovlad.ru
    Cайт http://www.edemvovlad.ru
    19.03.2020 04:00:07
    Avatar of kpaoaIncowkpaoaIncow
    viagra generic generic viagra <a href="http://royalathenaeum.com/ #">generic viagra </a> generic viagra buy viagra

    generic viagra buy viagra <a href=http://biblioteh.ru>viagra generic </a> buy viagra generic viagra
    25.03.2020 09:06:43
    Avatar of boohtIncowboohtIncow
    rhino instead of viagra generic viagra sales <a href=" https://pharm-usa-official.com/# #">levitra vs viagra </a> how many days do you have to fill a prescription for viagra natural viagra

    best way to get viagra to work what if viagra doesn't work <a href=https://pharm-usa-official.com/#>viagra generic </a> does viagra help libido natural viagra juice

    https://changacaocap.com/2020/03/12/philippine-casinos-seek-exemption-from-upcoming-72/?unapproved=83&moderation-hash=f433db93b493fa8f8bace2d4c4090741#comment-83
    https://globalresearchsyndicate.com/2020/03/14/what-the-new-european-travel-ban-means-for-air-travelers/?unapproved=624&moderation-hash=383f06c39869e1da234526ae26eeac48#comment-624
    https://sportsoneclt.com/guide-to-a-safer-barbecue-with-less-cancer-risk/?unapproved=392&moderation-hash=679d0cc4ef0ddfdcca0c5dfe5005477d#comment-392
    https://tekkibytes.com/how-to-become-famous-on-tiktok-fast/?unapproved=18922&moderation-hash=b5fe48768c8464f95dd0919ddfa32fed#comment-18922
    http://www.pmochina.com/content.aspx?id=1140&fid=0#commentsReplyer
    Captcha Обновить
    Go Top