Игорь Чакрыгин Игорь Чакрыгин

У любой задачи существует по крайней мере одно очевидное и невероятно простое для понимания неправильное решение

Sphinx - Подключение к Sphinx из .NET

В этой статье я хочу немного отвлечься от рассказа про сам Sphinx и немного поговорить о том, как взаимодействовать с ним из программы, написанной на языке C#.

Как я уже упоминал ранее, наиболее простым и удобным способом взаимодействия со Sphinx является язык запросов SphinxQL, который сильно напоминает обычный SQL. Сами запросы можно выполнять, подключившись к Sphinx как к обычной базе данных MySQL, поскольку Sphinx умеет её эмулировать.

Тем не менее даже используя официальный коннектор MySQL для .NET, взятый с сайта mysql.com, можно столкнуться с некоторыми сложностями, о решении которых я бы и хотел поговорить в этой статье.

Приложение

Прежде всего нам потребуется Sphinx хотя бы с одним настроенным индексом. Воспользуемся индексом product, настройку которого я описывал в одной из предыдущих статей (в примере 1).

После того, как у нас будет настроенный индекс, откроем Visual Studio и создадим обычное консольное приложение. Чтобы это приложение могло взаимодействовать со Sphinx, нам необходимо подключить к нему коннектор MySQL, и тут возникает вопрос: какую версию коннектора выбрать?

Версии коннектора

Честно говоря, ещё неделю назад для я был абсолютно уверен в том, что любой коннектор версии 5.*.* должен нормально работать со Sphinx, поскольку именно эту версию (точный номер, к сожалению, не помню) мы регулярно используем на работе. Каково же было моё удивление, когда перепробовав все версии, доступные на сайте mysql.com я убедился, что все они при подключении к Sphinx кидают ArgumentNullException.

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

select timediff( curtime(), utc_time() )

Этот запрос, вполне корректный для MySQL, Sphinx обработать не может и возвращает ошибку.

К счастью, немного поэкспериментировав с другими версиями я обнаружил, что версии коннектора с 6.2.* по 6.5.* нормально работают, поэтому вам я рекомендую использовать одну из них.

Добавим коннектор MySQL версии 6.5.4 в наше приложение. Для этого в Visual Studio откроем Package Manager Console (Tools - Library Package Manager - Package Manager Console) и введём команду:

Install-Package MySql.Data -Version 6.5.4

Код

Теперь мы можем приступить к написанию кода. Изменим метод Main следующим образом:

public static void Main(string[] args)
{
    var connectionString = "Server=127.0.0.1;Port=9306;Character Set=utf8";

    var query = "select id, name, price from product";

    using (var connection = new MySqlConnection(connectionString))
    using (var command = new MySqlCommand(query, connection))
    {
        connection.Open();

        using (var reader = command.ExecuteReader())
        {
            while (reader.Read())
            {
                var id = reader.GetInt32("id");
                var name = reader.GetString("name");
                var price = reader.GetFloat("price");
                Console.WriteLine("{0}\t{1}\t{2:0.00}", id, name, price);
            }
        }
    }
}

Как вы видите, подключение к Sphinx практически ни чем не отличаются от подключения к SQL Server. Все используемые классы имеют тот же набор методов и лишь немного отличаются названием.

Connector/Net no longer supports server versions prior to 5.0

Если мы прямо сейчас попробуем запустить наше приложение, то увидим ошибку «Connector/Net no longer supports server versions prior to 5.0». Возникает она, потому что наш коннектор подключаясь к Sphinx считает, что на самом деле подключается к базе данных MySQL, и запрашивает номер версии. Sphinx при этом возвращает версию 4, поскольку именно она задана по умолчанию. Коннектор, в свою очередь, возвращает ошибку, сообщая нам, что он не может работать с базой данных, версия которой ниже 5.

Чтобы изменить это поведение и вернуть номер версии, который бы удовлетворил используемый нами коннектор, воспользуемся опцией mysql_version_string блока searchd.

Добавим эту опцию в файл конфигурации Sphinx, указав номер версии 5.0.0:

searchd
{
    ...
    mysql_version_string = 5.0.0
}

Перезапустим Sphinx, чтобы изменения в файле конфигурации вступили в силу. Это можно сделать либо перезапустив службу Sphinx в панели управления (Пуск - Панель управления - Администрирование - Службы), либо через командную строку, последовательно введя две команды:

net stop Sphinx
net start Sphinx

Теперь, если мы снова запустим нашу программу, то увидим на экране список товаров.

Скачать демо (Console Application, .NET 4.5)

5 комментариев

  1. Прошу прощения, что пишу сюда. Но не нашел, куда еще можно написать. Ты наверно заметил (хотя кто знает), что у тебя в заголовке страниц отображается адрес страницы.

    ОтветитьУдалить
    Ответы
    1. Большое спасибо! Видел это, но потом забыл =)
      Там даже не адрес, там просто ничего нет. Видимо где-то в шаблоне Blogger`а я накосячил.

      Удалить
    2. Вот, теперь куда лучше :)

      Удалить
  2. Ну да. Многие коннекторы работают на костылях.
    Питоновский до определённого момента вообще падал, пытаясь распарсить VersionString.
    Собственно, из-за них и навставляли "хакерские" опции, позволяющие сфинксу выдать некую точную строку, как свою версию (а на самом деле эта строка не имеет отношения к реальной версии сфинкса).
    А разные вспомогательные запросы из коннектора (кто я? где я? какое сегодня число? а какая тут локаль?), в коде сфинкса закрыты загулками. Как раз-таки из-за .net-коннекторов. Но, очевидно, что заглушки не все. Нужно просто открывать багу в багтреккере, если новая версия коннектора вдруг не работает.
    И желательно к такой баге прикладывать дамп полного протокола общения коннектора с демоном при подключении (там часто далеко не одна команда летит; а дамп позволит добавить их все, без итераций "пофиксили? - а нифига, новая ошибка - переоткрываем багу!")

    ОтветитьУдалить
  3. Роман Максимович13 августа 2014 г. в 17:46

    Привет, можно ли использовать Dapper.Net для работы с Sзhinx? После стать про Joined и MultiValue немного засомневался, может быть кто-то уже использовал?

    ОтветитьУдалить

© Игорь Чакрыгин. Все права защищены при помощи чёрной магии. Технологии Blogger.