<?php /** * elasticsearch封裝類 * @author joniding * @date 2019-07-19 */ namespace PhpLib\Ec\Helpers; use Elasticsearch\ClientBuilder; use Illuminate\Http\Request; class ElasticSearch { public $config; public $api; public $index_name; public $index_type; public function __construct($index_name,$index_type) { try{ //加載配置文件 $this->config = config('elasticsearch'); //構建客戶端對象 $this->api = ClientBuilder::create()->setHosts($this->config['hosts'])->build(); $this->index_name = $index_name; $this->index_type = $index_type; }catch (\Exception $e){ throw $e; } } /** * 初始化索引參數 * @author joniding * @return array */ public function initParams() { return [ 'index' => $this->index_name, 'type' => $this->index_type, ]; } /** * 創建一個索引 * @author joniding * @param $settings * @return array * @throws \Exception */ public function createIndex($settings = []) { try{ $initParams['index'] = $this->index_name; !empty($settings) && $initParams['body']['settings'] = $settings; $res = $this->api->indices()->create($initParams); }catch(\Exception $e){ throw $e; } return $res; } /** * 更新索引的映射 mapping * @author joniding * @param $data * @return array * @throws \Exception */ public function setMapping($data) { try{ $initParams = $this->initParams(); $initParams['body'] = $data; $res = $this->api->indices()->putMapping($initParams); }catch (\Exception $e){ throw $e; } return $res; } /** * 獲取索引映射 mapping * @author joniding * @return array * @throws \Exception */ public function getMapping() { try{ $initParams = $this->initParams(); $res = $this->api->indices()->getMapping($initParams); }catch (\Exception $e){ throw $e; } return $res; } /** * 向索引中插入數據 * @author joniding * @param $data * @return bool * @throws \Exception */ public function add($data) { try{ $params = $this->initParams(); isset($data['id']) && $params['id'] = $data['id']; $params['body'] = $data['body']; $res = $this->api->index($params); }catch (\Exception $e){ throw $e; } if (!isset($res['_shards']['successful']) || !$res['_shards']['successful']){ return false; } return true; } /** * 批量插入數據 * @author joniding * @param $data * @return array * @throws \Exception */ public function bulk($data) { try{ if (empty($data['body'])) return false; $params = $this->initParams(); $params['body'] = $data['body']; $res = $this->api->bulk($params); }catch (\Exception $e){ throw $e; } return $res; } /** * 檢測文檔是否存在 * @param $id * @return array|bool * @throws \Exception */ public function IndexExists($id) { try{ $params = $this->initParams(); $params['id'] = $id; $res = $this->api->exists($params); }catch (\Exception $e){ throw $e; } return $res; } /** * 單字段模糊查詢 * 滿足單個字段查詢(不帶分頁+排序)match 分詞查詢 * @author joniding * @param $data * @return array * @throws \Exception */ public function search($data = []) { try{ $params = $this->initParams(); if (!empty($data)){ $field = key($data); $query = [ 'match' => [ $field => [ 'query' => $data[$field], 'minimum_should_match' => '90%' //相似度,匹配度 ] ] ]; $params['body']['query'] = $query; } $res = $this->api->search($params); }catch (\Exception $e){ throw $e; } return $res; } /** * 根據唯一id查詢數據 * @author joniding * @param $id * @return array * @throws \Exception */ public function searchById($id) { try{ $params = $this->initParams(); $params['id'] = $id; $res = $this->api->get($params); }catch (\Exception $e){ throw $e; } return $res; } /** * 根據關鍵字查詢數據 * 多個字段查詢:multi_match * @author joniding * @param $data * $data['condition'] 條件組合 * $data['es_size'] 每頁顯示數量 * $data['es_from'] 從第幾條開始 * $data['es_sort_field'] 自定義排序字段 * @return array|bool * @throws \Exception */ public function searchMulti($data = []) { try{ if (!is_array($data)){ return []; } $params = $this->initParams(); if (array_key_exists('fields',$data)){ $params['_source'] = $data['fields']; } //分頁 if (array_key_exists('page_size',$data)){ $params['size'] = !empty($data['page_size'])?$data['page_size']:1; //前端頁碼默認傳1 $params['from'] = !empty($data['page'])?($data['page']-1)*$params['size']:0; unset($data['page_size'],$data['page']); } //排序 if (array_key_exists('sort_field',$data)){ $sort_file = !empty($data['sort_field'])?$data['sort_field']:'total_favorited'; $sort_rule = !empty($data['sort_rule'])?$data['sort_rule']:'desc'; $params['body']['sort'][] = [ ''.$sort_file.'' => [ 'order' => ''.$sort_rule.'', ] ]; unset($data['sort_field'],$data['sort_rule']); }else{ // $params['body']['sort'][] = [ // 'created_at' => [ // 'order' => 'desc', // ] // ]; } /** * 深度(滾動)分頁 */ if (array_key_exists('scroll',$data)){ $params['scroll'] = $data['scroll']; } //條件組合 if (array_key_exists('condition',$data)){ $query = []; $condition = $data['condition']; /** * 組合查詢 */ if (array_key_exists('bool',$condition)){ //必須滿足 if (array_key_exists('must',$condition['bool'])){ foreach ($condition['bool']['must'] as $key => $val){ if (is_array($val)){ $query['bool']['must'][]['range'] = [ $key => [ 'gte' => $val[0], 'lte' => $val[1] ] ]; }else{ $query['bool']['must'][]['match'] = [ $key => $val ]; } } } } !empty($query) && $params['body']['query'] = $query; } $res = $this->api->search($params); }catch (\Exception $e){ throw $e; } return $res; } /** * 查詢索引是否存在 * @return array|bool * @throws \Exception */ public function exist() { try{ $params['index'] = $this->index_name; $res = $this->api->indices()->exists($params); }catch (\Exception $e){ throw $e; } return $res; } /** * 根據唯一id刪除 * @author joniding * @param $id * @return bool * @throws \Exception */ public function delete($id) { try{ $params = $this->initParams(); $params['id'] = $id; $res = $this->api->delete($params); }catch (\Exception $e){ throw $e; } if (!isset($res['_shards']['successful'])){ return false; } return true; } /** * 聚合統計,方差 * @param $data * @return array * @throws \Exception * @author:joniding * @date:Times */ public function searchAggs($data) { try{ if (!is_array($data)){ return []; } $query= []; $params = $this->initParams(); $params['size'] = 0; /** * 條件組合過濾,篩選條件 */ if (array_key_exists('condition',$data)){ $condition = $data['condition']; if (array_key_exists('bool',$condition)){ //必須滿足 if (array_key_exists('must',$condition['bool'])){ foreach ($condition['bool']['must'] as $key => $val){ if (is_array($val)){ $query['bool']['must'][]['range'] = [ $key => [ 'gte' => $val[0], 'lte' => $val[1] ] ]; }else{ $query['bool']['must'][]['match'] = [ $key => $val ]; } } $params['body']['query'] = $query; } } } //分組、排序設置 if (array_key_exists('agg',$data)){ $agg = []; //字段值 if (array_key_exists('terms',$data['agg'])){ $agg['_result']['terms'] = [ 'field' => $data['agg']['terms'], 'size' => 500, ]; if (array_key_exists('order',$data['agg'])){ foreach ($data['agg']['order'] as $key => $val){ $fields = 'result.'.$key; $agg['_result']['terms']['order'] = [ $fields => $val ]; unset($fields); } } } //統計 if (array_key_exists('field',$data['agg'])){ $agg['_result']['aggs'] = [ 'result' => [ 'extended_stats' => [ 'field' => $data['agg']['field'] ] ] ]; } //日期聚合統計 if (array_key_exists('date',$data['agg'])){ $date_agg = $data['agg']['date']; //根據日期分組 if (array_key_exists('field',$date_agg)){ $agg['result'] = [ 'date_histogram' => [ 'field' => $data['agg']['date']['field'], 'interval' => '2h', 'format' => 'yyyy-MM-dd HH:mm:ss' ] ]; } if (array_key_exists('agg',$date_agg)){ //分組 if (array_key_exists('terms',$date_agg['agg'])){ $agg['result']['aggs']['result']['terms'] = [ 'field' => $date_agg['agg']['terms'], 'size' => 100, ]; } //統計最大、最小值等 if (array_key_exists('stats',$date_agg['agg'])){ $agg['result']['aggs']['result']['aggs'] = [ 'result_stats' => [ 'extended_stats' => [ 'field' => $date_agg['agg']['stats'] ] ] ]; } } } $params['body']['aggs'] = $agg; } \Log::info(json_encode($params)); $res = $this->api->search($params); }catch (\Exception $e){ throw $e; } return $res; } /** * 批量查詢,只能根據id來查 * @param $data * @return array * @throws \Exception * @author:joniding * @date:2019/8/5 19:51 */ public function mGet($data) { try{ if (!is_array($data)) return []; //初始化索引 $params = $this->initParams(); if (array_key_exists('fields',$data)){ $query['ids'] = $data['fields']; $params['body'] = $query; } $res = $this->api->mget($params); return $res; }catch (\Exception $e){ throw $e; } } /** * 深度分頁 * @param $data * @return array * @throws \Exception * @author:joniding * @date:2019/8/16 14:49 */ public function scroll($data) { try{ $params = [ 'scroll_id' => $data['scroll_id'], 'scroll' => '1m' ]; $res = $this->api->scroll($params); // \Log::info(json_encode($params)); if (isset($res['_scroll_id']) && $res['_scroll_id'] != $data['scroll_id']){ $this->api->clearScroll(['scroll_id' => $data['scroll_id'] ]); } return $res; }catch(\Exception $e){ throw $e; } } }