Yii2整合Elasticsearch(二)
阿新 • • 發佈:2018-11-11
背景知識:
- 全文搜尋可以簡單地分為兩類,一種是順序掃描,即我們常見的使用 like %keyword% 方式,掃描整張資料表,在每一條記錄中查詢;另一種就是索引掃描。elasticsearch就是後者。
- 索引掃描分為兩部分:建立索引和搜尋索引。建立索引的主要步驟是:對原資料進行分詞處理(去掉標點和一些無意義的詞等等),將得到的詞元交給語言處理元件(例如將複數變為單數,將過去式變為一般式等等),最後再將詞元交給索引元件建立索引。搜尋索引的主要步驟:對使用者輸入的內容進行分詞語言等處理之後,根據詞元搜尋索引,找到對應的文件id,再根據文件id獲得結果。
- logstash可以理解為是一個管道,資料從輸入端傳輸到輸出端,當然你還可以在管道中防止一些濾網來過濾資料,感興趣的讀者可以詳細瞭解一下。
- 在使用ES的時候,注意版本,因為版本和版本之間的差距還是很大的
- 在操作ES的時候可以考慮使用官方的視覺化工具kibana,或者使用postman,curl命令,當然也可以使用elasticsearch-head,github主頁。
- 本文基於蘋果系統做介紹。
在上一篇文章中介紹了ES的安裝以及基礎知識,還擴充套件瞭如何使用logstash將mysql的資料匯入到ES中。本文將介紹Yii2框架中如何使用ES。
1.第一步安裝擴充套件:
#區域性安裝 php composer.phar require --prefer-dist yiisoft/yii2-elasticsearch:"~2.0.0" #全域性安裝 composer require --prefer-dist yiisoft/yii2-elasticsearch:"~2.0.0"
2.在web應用的配置檔案web.php增加如下的配置:
return [ //.... 'components' => [ 'elasticsearch' => [ 'class' => 'yii\elasticsearch\Connection', 'nodes' => [ ['http_address' => '127.0.0.1:9200'], // configure more hosts if you have a cluster ], ], ] ];
3.建立一個搜尋類,基於es元件提供的ActiveRecord:
<?php
namespace app\services;
use yii\elasticsearch\ActiveRecord;
class SearchGoods extends ActiveRecord{
#定義從es中返回結果的欄位
public function attributes()
{
return ['goods_id','name','descr','is_sale','price','sale_price','picture'];
}
#定義索引
public static function index(){
return 'yii';
}
#定義文件型別
public static function type(){
return 'doc';
}
}
4.在介紹如何使用上述定義的SearchGoods來進行搜尋之前,先來講一下原生基於API的方式:基於上一篇文章的例子,如果要查詢yii索引下goods型別中name含有“你好”的的文件:
POST http://localhost:9200/yii/goods/_search
{
"query":{
"match":{
"name":"你好"
}
}
}
那麼如果我要檢視name或者descr中包含“你好”的文件呢?
POST http://localhost:9200/yii/goods/_search
{
"query":{
"multi_match":{
"query":"你好",
"fields":["name","descr"]
}
}
}
由於我們在上一篇文件中給ES配置了IK分詞,因此我們可以使用IK提供的高亮顯示的功能,例如還是上面的例子,但是要求“你好”這個關鍵字高亮顯示:
POST http://localhost:9200/yii/goods/_search
{
"query":{
"multi_match":{
"query":"你好",
"fields":["title","descr"]
}
},
"highlight" : {
#左標籤
"pre_tags" : ["<i>"],
#右標籤
"post_tags" : ["</i>"],
#高亮的欄位
"fields" : {
"descr" : {},
"name":{}
}
}
}
#上面的配置的意思就是:例如有一個文件的內容是{"name":"你好,星期天","descr":"今天天氣真好呀"}
#當你搜索"你好"時,這個文件就會被搜尋出來,並且結果會有一個highlight屬性,值為:
#{"name":"<i>你好</i>,星期天"}
#基於上面的配置,如果想要“你好”在搜尋結果中以紅色顯示,那麼只要在搜尋結果頁中加上如下的css樣式即可:
<style>
i{
color:red;
}
</style>
以上就是原生API的查詢方法,基於這個原理,我們再來看看使用SearchGoods這個類如何做查詢:
<?php
namespace app\controllers;
use app\modules\admin\models\Goods;
use app\services\SearchGoods;
class GoodsController extends BaseController{
#商品控制器中新增基於es搜尋的方法
public function actionSearch(){
$hightlight=[
#左標籤,配合前端.highlight這個類來實現高亮
"pre_tags"=>['<span class="highlight">'],
"post_tags"=>['</span>'],
#在原生api中寫的是{}表示空物件,因此使用php的stdClass來表示空物件
"fields"=>[
"name"=>new \stdClass(),
'descr'=>new \stdClass()
]
];
$key=\Yii::$app->request->get('keyword');
$res=SearchGoods::find()->query([
'multi_match'=>[
'query'=>$key,
"fields"=>['name','descr']
]
])->highlight($hightlight)->all();
return $this->render('search',compact('res'));
}
}
#注意:你完全可以拿SearchGoods這個類當作平常的活動記錄類使用,因為yii\elasticsearch\ActiveRecord這個類也繼承了 yii\db\BaseActiveRecord;
5.以上就是Yii2整合ES的過程,需要注意的點:
- 可以將部分欄位資訊存入到ES中,然後根據ES返回的搜尋結果回溯資料表獲取更多的資訊,這種方式效率低但是節省空間。第二種方式就是將需要的所有欄位資訊全部存入到ES中,這種方式就不用回溯資料表了效率高但是空間消耗大
- logstash從mysql增量向ES中匯入資料時,如果mysql中資料更新或者新增了都是會同步的,但是如果刪除了logstash並不會在ES中刪除相應的資料。解決方案可以嘗試在資料刪除後手動向ES傳送相應的刪除api請求進行刪除。
- 可以在logstash的mysql配置檔案中配置schedule項來實現自動增量