yii2.0框架中使用elasticsearch


自己寫的公共類,如有不完善或錯誤地方,歡迎更正

 

common/Elasticseatch.php

  1 <?php
  2 
  3 namespace app\common;
  4 
  5 use yii;
  6 use yii\elasticsearch\ActiveRecord;
  7 use yii\data\Pagination;
  8 
  9 
 10 class Elasticsearch extends ActiveRecord{
 11 
 12     /**
 13      * 使用的數據庫連接
 14      */
 15     public static function getDb(){
 16         return \Yii::$app->get('elasticsearch');
 17     }
 18 
 19     /**
 20      * [mapConfig mapping配置]
 21      * 返回這個模型的映射
 22      *
 23      * properties配置說明
 24      *
 25      * 屬性
 26      * 數據類型 string(已廢棄) byte short integer long float double boolean date binary(二進制) ip(以字符換格式存IPv4地址) token_count(存儲索引的字數信息)
 27      *
 28      * 公共屬性
 29      * index            -> analyzed(被分析,編入索引,產生的token能被搜索到) not_analyzed(不被分析,使用原始值編入索引,在索引中作為單個詞) no(不編入索引,無法搜索該字段)
 30      * store            -> 指定是否將字段的原始值寫入索引,默認值是no,字段值被分析,能夠被搜索,但是,字段值不會存儲,這意味着,該字段能夠被查詢,但是不會存儲字段的原始值  通常情況字段值已經是_source字段的一部分,可以只檢索需要的
 31      * boost            -> 字段級別的助推,默認值是1,定義了字段在文檔中的重要性/權重
 32      * include_in_all   -> 該屬性指定當前字段是否包括在_all字段中,默認值是true
 33      * copy_to          -> 該屬性指定一個字段名稱,ElasticSearch引擎將當前字段的值復制到該屬性指定的字段中
 34      * doc_values       -> 文檔值是存儲在硬盤上的索引時(indexing time)數據結構,對於not_analyzed字段,默認值是true,analyzed string字段不支持文檔值;如果您確定不需要對字段進行排序或聚合,或者從腳本訪問字段值,則可以禁用doc值以節省磁盤空間
 35      * fielddata        -> 字段數據是存儲在內存中的查詢時(querying time)數據結構,只支持analyzed string字段
 36      * null_value       -> 該屬性指定一個值,當字段的值為NULL時,該字段使用null_value代替NULL值;在ElasticSearch中,NULL 值不能被索引和搜索,當一個字段設置為NULL值,ElasticSearch引擎認為該字段沒有任何值,使用該屬性為NULL字段設置一個指定的值,使該字段能夠被索引和搜索。
 37      *
 38      * 常用其他屬性
 39      * analyzer         -> 該屬性定義用於建立索引和搜索的分析器名稱,默認值是全局定義的分析器名稱,該屬性可以引用在配置結點(settings)中自定義的分析器
 40      * search_analyzer  -> 該屬性定義的分析器,用於處理發送到特定字段的查詢字符串
 41      * ignore_above     -> 該屬性指定一個整數值,當字符串字段(analyzed string field)的字節數量大於該數值之后,超過長度的部分字符數據將不能被analyzer處理,不能被編入索引;對於 not analyzed string字段,超過長度的部分字符將被忽略,不會被編入索引。默認值是0,禁用該屬性;
 42      * position_increment_gap   -> 該屬性指定在相同詞的位置上增加的gap,默認值是100;
 43      * index_options    -> 索引選項控制添加到倒排索引(Inverted Index)的信息
 44      * [
 45      *      docs        -> 只索引文檔編號(Doc Number)
 46      *      freqs       -> 索引文檔編號和詞頻率(term frequency)
 47      *      positions   -> 索引文檔編號,詞頻率和詞位置(序號)
 48      *      offsets     -> 索引文檔編號,詞頻率,詞偏移量(開始和結束位置)和詞位置(序號)
 49      *      默認情況下,被分析的字符串(analyzed string)字段使用positions,其他字段使用docs
 50      * ]
 51      *
 52      * 數值類型的其他屬性
 53      * precision_step   -> 該屬性指定為數值字段每個值生成的term數量,值越低,產生的term數量越高,范圍查詢越快,索引越大,默認值是4
 54      * ignore_malformed -> 忽略格式錯誤的數值,默認值是false,不忽略錯誤格式,對整個文檔不處理,並且拋出異常
 55      * coerce           -> 默認值是true,嘗試將字符串轉換為數值,如果字段類型是整數,那么將小數取整
 56      *
 57      * 日期類型的其他屬性
 58      * format           -> 指定日期的格式,例如:“yyyy-MM-dd hh:mm:ss”
 59      * ignore_malformed -> 忽略錯誤格式,默認值是false,不忽略錯誤格式
 60      *
 61      * fields           -> 在fields屬性中定義一個或多個字段,該字段的值和當前字段值相同,可以設置一個字段用於搜索,一個字段用於排序等
 62      *      "properties":
 63      *      {
 64      *          "id":{
 65      *              "type":"long",
 66      *              "fields":{
 67      *                  "id2":{"type":"long","index":"not_analyzed"}
 68      *              }
 69      *          }
 70      *      }
 71      * _all             -> 表示存儲其他字段的數據以便搜索,默認情況下,_all字段是啟用的,包含了索引中所有字段的數據,然而這一字段使索引變大,如果不需要,請禁用該字段,或排除某些字段
 72      * "_all":{"enabled":false}
 73      * _source          -> 表示在生成索引的過程中,存儲發送到ElasticSearch的原始JSON文檔,默認情況下,該字段會被啟用,因為索引的局部更新功能依賴該字段。
 74      * _routing         -> 路由字段 公式:shard_num = hash(_routing) % num_primary_shards  使用的默認字段是_id,設置required為true,表示路由字段在進行索引的CRUD操作時必需顯式賦值。
 75      *
 76      * 不可配置的元字段
 77      * _index           -> 返回文檔所屬的索引
 78      * _uid             -> 返回文檔的type和id
 79      * _type            -> 返回文檔類型(type)
 80      * _id              -> 返回文檔的ID;
 81      * _size            -> 返回文檔的_source字段中函數的字節數量;
 82      * _field_names     -> 返回文檔中不包含null值的字段名稱;
 83      *
 84      */
 85     public static function mapConfig(){
 86         return [
 87             // 根據type來獲取model->attributes
 88             'member' => [
 89                 'properties' => [
 90                     'user_id'    => ['type' => 'integer'],
 91                     'user_name'     => ['type' => 'text'],
 92                     'email'         => ['type' => 'keyword'],
 93                     'qq'            => ['type' => 'keyword'],
 94                     'edit_time'     => ['type' => 'date', 'format' => 'yyyy-MM-dd HH:mm:ss||yyyy-MM-dd']
 95                 ]
 96             ],
 97             // 根據type來獲取model->attributes
 98             'member2' => [
 99                 'properties' => [
100                      'user_id'      => ['type' => 'integer'],
101                      'user_name'        => ['type' => 'text'], 
               'edit_time' => ['type' => 'date', 'format' => 'yyyy-MM-dd HH:mm:ss||yyyy-MM-dd'] 102 ] 103 ] 104 ]; 105 } 106 107 /** 108 * 獲取群集中所有索引映射 109 */ 110 public static function getMapping(){ 111 $db = self::getDb(); 112 $command = $db->createCommand(); 113 return $command->getMapping(); 114 } 115 116 /** 117 * 根據索引主鍵獲取相關信息 118 * 支持單個或多個 119 */ 120 public function getByKey($id){ 121 if(is_array($id)){ 122 $res = self::mget($id); 123 }else{ 124 $res = self::get($id); 125 } 126 return $res; 127 } 128 129 /** 130 * 單個 131 * 默認返回object對象 返回數組 添加->asArray() 132 */ 133 public function getOne($query = []){ 134 $es_query = self::find(); 135 136 // 匹配查詢 137 if($query && !empty($query)){ 138 $es_query->query($query); 139 } 140 // 分組 141 $res = $es_query->one(); 142 143 return $res; 144 } 145 146 /** 147 * 列表 148 * 默認返回object對象 返回數組 添加->asArray() 149 * search 與 all 區別在於 all是在search基礎上處理再拿出結果 150 */ 151 public function getList($query = [], $order = [], $offset = 0, $limit = 20){ 152 $es_query = self::find(); 153 154 // 匹配查詢 155 if($query && !empty($query)){ 156 $es_query->query($query); 157 } 158 // 排序 159 if($order && !empty($order)){ 160 $es_query->orderby($order); 161 } 162 // 分組 163 $res = $es_query->offset($offset)->limit($limit)->asArray()->all(); 164 $list = array_column($res, '_source'); 165 166 return $list; 167 } 168 169 /** 170 * 分頁列表 171 * 默認返回object對象 返回數組 添加->asArray() 172 * search 與 all 區別在於 all是在search基礎上處理再拿出結果 173 */ 174 public function getPageList($query = [], $order = []){ 175 $es_query = self::find(); 176 177 // 匹配查詢 178 if($query && !empty($query)){ 179 $es_query->query($query); 180 } 181 // 排序 182 if($order && !empty($order)){ 183 $es_query->orderby($order); 184 } 185 186 // 分組 187 $count = $es_query->search(); 188 // 分頁 189 $pages = new Pagination(['totalCount' => $count['hits']['total']]); 190 // 分組 191 $res = $es_query->offset($pages->offset)->limit($pages->limit)->asArray()->all(); 192 $list = array_column($res, '_source'); 193 194 return ['list' => $list, 'pages' => $pages]; 195 } 196 197 /** 198 * 列表 199 * 默認返回object對象 返回數組 添加->asArray() 200 * search 與 all 區別在於 all是在search基礎上處理再拿出結果 201 */ 202 public function getFilterList($filter_arr = [], $query = [], $order = [], $offset = 0, $limit = 20){ 203 $es_query = self::find(); 204 205 // 過濾器 206 if($filter_arr && !empty($filter_arr)){ 207 $es_query->postFilter($filter_arr); 208 } 209 // 匹配查詢 210 if($query && !empty($query)){ 211 $es_query->query($query); 212 } 213 // 排序 214 if($order && !empty($order)){ 215 $es_query->orderby($order); 216 } 217 // 分組 218 $res = $es_query->offset($offset)->limit($limit)->all(); 219 220 return $res; 221 } 222 223 /** 224 * 獲取高亮列表 225 * 默認返回object對象 返回數組 添加->asArray() 226 * search 與 all 區別在於 all是在search基礎上處理再拿出結果 227 * 循環使用$v->highlight獲取高亮列表 228 */ 229 public function getHighLightList($highlight_arr = [], $query = [], $offset = 0, $limit = 20){ 230 $es_query = self::find(); 231 232 // 高亮 233 if($highlight_arr && !empty($highlight_arr)){ 234 $es_query->highlight($highlight_arr); 235 } 236 // 匹配查詢 237 if($query && !empty($query)){ 238 $es_query->query($query); 239 } 240 // 分組 241 $res = $es_query->offset($offset)->limit($limit)->all(); 242 243 return $res; 244 } 245 246 /** 247 * 獲取聚合列表 248 * 默認返回object對象 返回數組 添加->asArray() 249 * search 與 all 區別在於 all是在search基礎上處理再拿出結果 250 */ 251 public function getAggList($aggregate_name, $addAggregate_arr = [], $query = [], $offset = 0, $limit = 20){ 252 $es_query = self::find(); 253 254 // 聚合 255 if($addAggregate_arr && !empty($addAggregate_arr)){ 256 $es_query->addAggregate($aggregate_name, $addAggregate_arr); 257 } 258 // 匹配查詢 259 if($query && !empty($query)){ 260 $es_query->query($query); 261 } 262 // 分組 263 $res = $es_query->offset($offset)->limit($limit)->search(); 264 265 return ['list' => $res['hits']['hits'], $aggregate_name => $res['aggregations'][$aggregate_name]]; 266 } 267 }

 

model/EsModel

 1 <?php
 2 
 3 namespace app\models;
 4 
 5 use app\common\Elasticsearch;
 6 
 7 class EsModel extends Elasticsearch{
 8 
 9     // _index _type _id 定義
10     // https://www.elastic.co/guide/cn/elasticsearch/guide/current/_Document_Metadata.html
11     public static $index_db_name = '';
12     public static $type_tb_name = '';
13 
14     // 索引名相當於庫名
15     public static function index(){
16         return self::$index_db_name;
17     }
18 
19     // 類別名相當於表名
20     public static function type(){
21         return self::$type_tb_name;
22     }
23 
24     // 屬性
25     public function attributes(){
26         $mapConfig = self::mapConfig();
27         return array_keys($mapConfig[self::$type_tb_name]['properties']);
28     }
29 
30     // 映射
31     public static function mapping(){
32         $mapConfig = self::mapConfig();
33         return [
34             static::type() => $mapConfig[self::$type_tb_name]
35         ];
36     }
37 
38     // 更新映射
39     public static function updateMapping(){
40         $db = self::getDb();
41         $command = $db->createCommand();
42         if(!$command->indexExists(self::index())){
43             $command->createIndex(self::index());
44         }
45         $res = $command->setMapping(self::index(), self::type(), self::mapping());
46         return $res;
47     }
48 
49     // 創建索引
50     public static function createIndex(){
51         $db = static::getDb();
52         $command = $db->createCommand();
53         $command->createIndex(static::index(), [
54             'settings' => [
55                 'index' => [
56                     // 指定新索引的時候不會立即生效,1s之后刷新生效  默認是1s
57                     'refresh_interval'      => '1s',
58                     // 索引分片個數  默認5片
59                     'number_of_shards'      => 5,
60                     // 每個分片副本個數  默認1個
61                     'number_of_replicas'    => 1
62                 ]
63             ],
64             'mappings' => static::mapping(),
65             //'warmers' => [ /* ... */ ],
66             //'aliases' => [ /* ... */ ],
67             //'creation_date' => '...'
68         ]);
69     }
70 
71     // 刪除索引
72     public static function deleteIndex(){
73         $db = static::getDb();
74         $command = $db->createCommand();
75         $res = $command->deleteIndex(static::index(), static::type());
76         return $res;
77     }
78 }

 

controller調用

1 // 調用ES
2 $model = new \app\models\EsModel();
3 $model::$index_db_name = 'index_name';
4 $model::$type_tb_name = 'type_name';

 

搜索的話按照上篇查詢請求體說明來就好了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM