Это правильный способ использования Sphinx из PHP?

Я только начинаю с Сфинкса. Пока я его успешно установил, получил таблицу под названием profiles в моей базе данных MySQL, и я смог получить правильные результаты с помощью PHP API. Я использую CodeIgniter, поэтому я включил PHP API по умолчанию в качестве библиотеки CodeIgniter.

В любом случае так выглядит мой код:

$query = $_GET['q'];
$this->load->library('sphinxclient');
$this->sphinxclient->setMatchMode(SPH_MATCH_ANY);
$result = $this->sphinxclient->query($query);

$to_fetch = array();
foreach($result['matches'] as $key => $match) {
  array_push($to_fetch, $key);
}

Массив $to_fetch содержит идентификаторы строк сопоставленной таблицы. Теперь я могу использовать типичный запрос MySQL, чтобы все соответствующие пользователи отображались на странице поиска так:

$query = 'SELECT * FROM profiles WHERE id IN('. join(',', $to_fetch) . ')';

Мой вопрос:

  • Это правильный путь? или существует ли по умолчанию "способ Sphinx сделать это", что было бы лучше для производительности.

  • во-вторых, все, что я верну в данный момент, это идентификатор строк таблицы соответствия. Я также хочу, чтобы часть текста в столбце соответствовала. Например, если кто-то ищет ключевое слово dog, а пользователь в таблице profiles имел в столбце about следующий текст:

    I like dogs. I also like ice cream.

Я бы хотел, чтобы Сфинкс вернулся:

I like <strong>dogs</strong>. I also like ice cream.

Как я могу это сделать? Я пытался играть с функцией buildExcerpts(), но не могу заставить ее работать.

ИЗМЕНИТЬ

Вот как я получаю отрывки сейчас:

// get matched user ids
$to_fetch = array();
foreach($result['matches'] as $key => $match) {
  array_push($to_fetch, $key);
}

// get user details of matched ids
$members = $this->search_m->get_users_by_id($to_fetch);

// build excerpts
$excerpts = array();
foreach($members as $member) {

    $fields = array(
        $member['about'],
        $member['likes'],
        $member['dislikes'],
        $member['occupation']
    );

    $options = array(
        'before_match'      => '<strong class="match">',
        'after_match'       => '</strong>',
        'chunk_separator'   => ' ... ',
        'limit'             => 60,
        'around'            => 3,
    );

    $excerpt_result = $this->sphinxclient->BuildExcerpts($fields, 'profiles', $query, $options);
    $excerpts[$member['user_id']] = $excerpt_result;
}

$excerpts_to_return = array();
foreach($excerpts as $key => $excerpt) {
    foreach($excerpt as $v) {
        if(strpos($v, '<strong class="match">') !== false) {
            $excerpts_to_return[$key] = $v;
        }
    }
}

Как вы можете видеть, я ищу каждый запрос в 4 разных столбцах mysql:

about
likes
dislikes
occupation

Из-за этого я не знаю, какой из 4 столбцов содержит сопоставленное ключевое слово. Это может быть любой из них или даже более одного. Поэтому у меня нет выбора, кроме как запустить содержимое всех 4 столбцов с помощью функции buildExcerpts().

Даже тогда я не знаю, какой из них buildExcerpts() вернулся с тегами <strong class="match">. Поэтому я запускаю проверку stpos на все значения, возвращаемые buildExcerpts(), чтобы, наконец, получить правильный отрывок и сопоставить его с пользователем, чей профиль он принадлежит.

Вы видите лучший способ, чем это, учитывая мою ситуацию, когда мне нужно сопоставлять содержимое четырех разных столбцов?

Ответ 1

Да, это выглядит неплохо. Одна вещь, чтобы вспомнить строки, возвращающиеся из Mysql, вероятно, не будет в порядке от сфинкса.

См. FAQ на сайте sphinx для использования FIELD(), но лично мне нравится помещать строки из sphinx в ассоциативный массив, а затем просто цикл, хотя сфинкс, который я бы перечислил, и получить строку из массива. Исключает фазу сортировки в целом за счет памяти!

Что касается выделения, да, настойчивость с помощью buildExcerpts - вот как это сделать.


изменить, чтобы добавить, эта демонстрация http://nearby.org.uk/sphinx/search-example5-withcomments.phps демонстрирует как получение строк из mysql, так и "сортировку" в приложении. И buildExcerpts.