2012-05-31 5 views
2

Я прочитал, что, чтобы иметь возможность ранжировать поиска Вы можете запросить MySQL так:CakePHP Полнотекстовый поиск MySQL с рейтингом

SELECT * , 
MATCH (title, body) AGAINST ('$search') AS rating 
FROM posts 
WHERE MATCH (title, body) AGAINST ('$search') 
ORDER BY rating DESC 

Есть ли способ сделать это в CakePHP 2.X? Кроме того, мне нужно сделать это, одновременно разбивая страницы на страницы. Поэтому я думаю, что мне нужно будет написать условие для paginator, а не прямой запрос.

Благодарим за помощь!

ответ

2

Хорошо, что мне потребовалось некоторое время ... Так, ключевой вопрос в том, чтобы получить рейтинг в результате матчей, сложная часть в этом запросе было специфическое поле:

MATCH (title, body) AGAINST ('$search') AS rating

I что я должен просто написать это поле в опции «field» в массиве разбиения на страницы. Полученный код был следующим:

$this->paginate = array(
      'limit' => 15, 
      'fields' => array('*', "MATCH (data) AGAINST ('$q') AS rating"), 
      'conditions' => "MATCH(SearchIndex.data) AGAINST('$q' IN BOOLEAN MODE)", 
      'order' => array(
       'rating' => 'desc', 
      ), 
    ); 
    $paginatedResults = $this->paginate('SearchIndex'); 

И это работало без проблем!

Я думаю, что это лучший способ добиться реальных результатов поиска с помощью Cake. Если у кого-то нет лучшей альтернативы :)

Поисковые фразы между двойными кавычками дадут вам результаты, которых вы ожидаете!

+0

Пожалуйста, смотрите комментарии http://stackoverflow.com/a/20326527/47573, без дополнительной защиты (что не ясно из контекста), это открывает приложение против SQL-инъекций (http://en.wikipedia.org/wiki/SQL_injection). – mark

+1

Возможно, вы захотите рассмотреть возможность создания рейтинга virtualField. Таким образом, он будет находиться внутри вашего массива SearchIndex. * $ this-> SearchIndex-> ​​virtualFields ['rating'] = "MATCH (SearchIndex.data) ПРОТИВ ('". $ q. "')"; * – styks

+0

Пожалуйста, улучшите свой ответ и исправьте SQL-инъекцию –

2

Я использовал вышеупомянутый вызов базы данных Томасом (спасибо), и он работает без проблем.

Однако код:

'conditions' => "MATCH(SearchIndex.data) AGAINST('$q' IN BOOLEAN MODE)", 

удаляет слой абстракции данных и открывает свой сайт для инъекции SQL.

Это, вероятно, не так хорошо (не полностью протестировали его), но попробовать:

'SearchIndex.data LIKE'=>'%'.$search.'%' 

Я надеюсь, что это полезно в некоторым образом.

3

использование, как это будет предотвратить MySQL инъекции слишком

array("MATCH(User.current_position) AGAINST(? IN BOOLEAN MODE)" => $srch_arr['text']) 
Смежные вопросы