php 封装 elasticsearch

<?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;
        }
    }


}

 

posted on 2020-03-13 17:55  小V_chen  阅读(1183)  评论(0编辑  收藏  举报

导航