FullText Search MySql - uniqcle/Yii2 GitHub Wiki

Поиск по всему содержимому, тем самым оценивается релевантность поиска.

Активно используется индекс. Т.е заранее прошлись по всем записям, по всем словам и составили словарь всех слов, которые встречаются.

Автомобиль - 73(6 раз), 266(4 раза), 49541(2раза)
Арбуз - 56475(4 раза), 73(3 раза), 899(1 раз)
Больше - 889(11), 87(2), 25756(1)
Вода - 6849(8), 882(1)
...

Слова составлены в алфавитном порядке.

Напр., Автомобиль встречается в записи 73 - 6 раз, в записи 266 - 4 раза, в записи 49541 - 2 раза и т.д.

Если слово нашлось, то мы берем все идентификаторы этих записи, ищем в БД и выводим записи этих идентификаторов. К тому же у нас есть мера релевантности.

Из минусов: индекс нужно постоянно поддерживать в актуальном состоянии.

Если из БД много читают, а добавляют немного, то индексы уместны. А если много добавляют, а мало читают, то индексы могут снизить производительность.

FullText Search

Добавляем индекс на то поле, по которому будет выполняться поиск.

Миграция console\migrations\m190909_062542_create_index_fulltext_content.php

Может занять некоторое время, если БД большая. К тому же на диске тратится место

use yii\db\Migration;

class m190909_062542_create_index_fulltext_content extends Migration
{

    public function safeUp()
    {
        $this->execute("ALTER TABLE news ADD FULLTEXT INDEX idx_content (content)"); 
        //$this->execute("ALTER TABLE news ADD FULLTEXT INDEX idx_title (title)"); 
    }

    public function safeDown()
    {
        $this->dropIndex('idx_content', 'news'); 
        //$this->dropIndex('idx_title', 'news');
    }
}

frontend\controllers\SearchController.php

namespace frontend\controllers; 

use Yii; 
use yii\web\Controller; 
use frontend\models\forms\SearchForm; 

class SearchController extends Controller 
{
	public function actionSimple(){
        ...
	}

	public function actionFulltext(){

		$model = new SearchForm();

		$result = null; 

		if( $model->load( Yii::$app->request->post() ) ){
			$result = $model->fullTextSearch(); 
		} 

		return $this->render('fulltext', [
			'model' => $model, 
			'result' => $result
		]); 
	}
}

frontend\models\forms\SearchForm.php

namespace frontend\models\forms;  

use yii\base\Model; 
use frontend\models\Search; 

class SearchForm extends Model 
{

	public $keyword; 

	public function rules(){
		return [
			['keyword', 'required'], 
			['keyword', 'trim']
		]; 
	}

 	public function simpleSearch(){
        ...
	} 

	public function fullTextSearch(){

		if( $this->validate() ){

		$model = new Search(); 

		return	$model->fullTextSearch( $this->keyword ); 
		}
	}
}

frontend\models\Search.php

namespace frontend\models; 

use Yii; 

 //Занимается логикой поиска
 class Search  
 {

 	public function simpleSearch($keyword){
        ...
 	}

 	public function fullTextSearch($keyword){
 	
                $params = [
 			':keyword' => $keyword
 		];

 		$sql = "SELECT * FROM news WHERE MATCH(content) AGAINST(:keyword) LIMIT 20"; 

 		return Yii::$app->db->createCommand($sql)->bindValues($params)->queryAll(); 
 	}
 }

frontend\views\search\fulltext.php

/* @var $this yii\web\View */
/* @var $form yii\bootstrap\ActiveForm */
/* @var $model \frontend\models\LoginForm */
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
use frontend\components\HighlightHelper; 

$this->title = 'Login User';
$this->params['breadcrumbs'][] = $this->title;
?>

<div class="site-signup">
    <h1><?= Html::encode($this->title) ?></h1>

    <p></p>
	<!-- Форма ввода --> 
    <div class="row">
        <div class="col-lg-5">
            <?php $form = ActiveForm::begin(['id' => 'form-signup']); ?>

                <?= $form->field($model, 'keyword')->textInput(['autofocus' => true]) ?>

                <div class="form-group">
                    <?= Html::submitButton('Search', ['class' => 'btn btn-primary', 'name' => 'signup-button']) ?>
                </div>

            <?php ActiveForm::end(); ?>
        </div>
    </div>

    <div class="row">
 	<!-- Область вывода --> 
    <?php if(is_array($result) && !empty($result)){ ?>
	<table class="table">
	  <thead class="thead-dark">
	    <tr>
	      <th scope="col">#</th>
	      <th scope="col">Title</th>
	      <th scope="col">Content</th>
	      <th scope="col">Status</th>
	    </tr>
	  </thead>
	  <tbody>
	<?php foreach($result as $item): ?>
	    <tr>
	      <th scope="row"><?=$item['id'] ?></th>
	      <td><?=$item['title']; ?></td>
	      <td><?php echo HighlightHelper::process($model->keyword, $item['content']);  ?></td>
	      <td><?=$item['status'];  ?></td>
	    </tr>
	<?php endforeach;  ?>

	  </tbody>
	</table>
	<?php } ?>		
				
     </div>
</div>
⚠️ **GitHub.com Fallback** ⚠️