zoukankan      html  css  js  c++  java
  • 搜索接口优化方案——elasticsearch分布式搜索引擎的基本使用

    前言:

        在开发项目中一般都会有搜索功能。如果是面向C端的搜索功能,往往都特别考验性能。比如普通的商城系统中的商品搜索或者一些资源的站内搜索。

        可能以前的做法就是对商品表做一个按名称或商品描述做模糊查询。更好一点的是对搜索关键字进行分词,并且专门建一个搜索词库表。不过前期需要对搜索词进行拆解然后幂集组合并于商品ID关联,搜索字与词库表的字以完全匹配的方式查询并找到商品ID。

        虽然建词库表也是不错的解决方法,但是还要拆解存库建索引,相对比较麻烦。所以也是在网上查询了解到了elasticsearch,打算以后做站内搜索用ES,下面就简单介绍一下他的基本使用方法。

    ES介绍:

         ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

    下载安装:

    1. 找到官网,按自己的系统下载对应版本,目前200多M。

        

    2. 解压后打开目录中的bin里的"elasticsearch.bat"就可以启动。

    3. 启动时间相对慢一点,以下只演示单机单节点使用,分布式可以后期配置。

    编码使用:

    以下是以ThinkPHP6.0.2进行演示使用,所以在ES服务开启后,先打开浏览器访问127.0.0.1:9200,如果返回下面表示成功开启。

    1. ThinkPHP6.0中通过composer install elasticsearch/elasticsearch 下载ES依赖包,如果composer慢可以试一下下载方法后再安装。

    并且每次要本地使用ES时都要先开启elasticsearch.bat文件,不然就会出现下面的提示。

    2. 在使用前需要理解一下ES的几个名词:索引,Type,文档,字段,映射。并且ES以restful风格进行查询,所以可以将前面的名词可以和MySQL的数据库,表,列,SQL关联一下。比如索引相当于MySQL的数据库,文档相当于表中的一条记录restful方式请求就类似于SQL语句。比如GET 索引名/Type/ID 可以获取文档数据,POST,PUT,DELETE等等创建索引,创建/修改/删除文档等可以查询官方文档,然后使用POSTMAN用不同的请求127.0.0.1:9200。

    3. 现在回到ThinkPHP6中,在安装ES依赖后。可以封装一个ES基本方法工具类。

    <?php
    
    
    namespace appcommonhelper;
    
    use ElasticsearchClientBuilder as ESClientBuilder;
    class Elasticsearch
    {
        protected $config = [
            "127.0.0.1:9200",
        ];
        protected $es;
    
        /*
         * @Title:  构造函数
         * @Author: 北桥苏
         * @Times:  2020/5/14 17:35
         * */
        public function __construct()
        {
            $this->es = $this->init();
        }
    
        /*
         * @Title ElasticSearch服务初始化
         * @Return object ES实例
         * */
        private function init()
        {
            // 从配置文件读取 Elasticsearch 服务器列表
            $builder = ESClientBuilder::create()->setHosts($this->config);
    
            // 应用调试模式
    //        if (env('APP_DEBUG')) {
    //            // 配置日志,Elasticsearch 的请求和返回数据将打印到日志文件
    //            $builder->setLogger(app('log')->error());
    //        }
            return $builder->build();
        }
    
        /*
         * @Title: 获取ES服务信息
         * @Return: ES服务的基本信息
         * */
        public function info()
        {
            return $this->es->info();
        }
    
        /*
         * @Titles: 创建索引
         * @Param: string $name 索引名
         * @Param: array $mappings 字段映射
         * @Return: boolean 创建结果
         * */
        public function index($name, $mappings=[])
        {
            $params = [
                'index' => $name,
                'body' => [
                    'settings' => [
                        'number_of_shards' => 1,                // 索引分片(一个索引可以分多个分片在不同的节点上)
                        'number_of_replicas' => 0,              // 索引分片副本
                    ]
                ]
            ];
            // 创建索引设置字段以及字段类型分词器等
            if($mappings) {
                $params['body']['mappings']['properties'] = $mappings;
            }
    
            return $this->es->indices()->create($params);
        }
    
        /*
         * @Title: 获取索引配置,可以获取单个索引,不传参数是节点上的所有索引
         * @Param: array $name 索引名数组
         * @Return:array 索引的名称分片副本数等数据
         * */
        public function getIndexConfig($name=[])
        {
            $params = [];
            if(!empty($name)) {
                $params = [
                    "index" => $name
                ];
            }
            return $this->es->indices()->getSettings($params);
        }
    
        /*
         * @Title: 创建/更改映射(创建索引时也可以指定映射-其实就是存储数据的字段类型)
         * @Param: string $name 索引名
         * @Param: array $data 字段设置
         * @Return boolean 修改结果
         * */
        public function putMapping($name, $data)
        {
            $params = [
                'index' => $name,
                'body' => [
                    '_source' => [
                        'enabled' => true
                    ],
                    'properties' => $data
                ]
            ];
    
            return $this->es->indices()->putMapping($params);
        }
    
        /*
         * @Tile: 获取索引设置的字段映射
         * @Param: string $name
         * @Return: array
         * */
        public function getMapping($name)
        {
            $params = ['index' => $name];
            return $this->es->indices()->getMapping($params);
        }
    
        /**
         * @Notes: 获取索引中的文档
         * @param $name 索引名称
         * @param $id 编号
         * @Return: 文档数据
         */
        public function getIndex($name, $id)
        {
            return $this->es->get(['index' => $name, 'id' => $id]);
        }
    
        /**
         * @Notes: 删除索引
         * @param $name 索引名称
         * @return array
         */
        public function deleteIndex($name)
        {
            return $this->es->indices()->delete(['index' => $name]);
        }
    
    
        /***********************文档部分********************************************************/
    
        /*
         * @Tiele: 在某索引中创建一个文档(如果索引未设置映射,添加文档会自动创建字段类型等)
         * @Param: string $name 索引名
         * @Param: array $data 文档数据
         * @Return array
         * */
        public function createDoc($name, $data)
        {
            $params = [
                'index' => $name,
                'id'    => $data['id'],
                'body'  => $data
            ];
            $response = $this->es->index($params);
            return $response;
        }
    
        /**
         * @Notes: 更新文档
         * @param $index 索引
         * @param $id 文档 id
         * @param $data 字段
         * @author: 北桥苏
         * @Time: 2020/4/21 9:51
         */
        public function updateDoc($index, $id, array $data)
        {
            $params = [
                'index' => $index,
                'id' => $id,
                //'type' => '_doc',
                'body' => [
                    'doc' => $data
                ]
            ];
    
            $this->es->update($params);
        }
    
        // 删除一个文档
        /*
         * @Tile: 删除一个文档
         * @Param: array $param 删除索引名,ID
         * @Return array
         * */
        public function delDoc($param)
        {
            $this->es->delete($param);
        }
    
        // 批量创建文档
        public function bulk($params)
        {
            return $this->es->bulk($params);
        }
    
        // 搜索
        public function queryData($index,$kye, $from = 0, $size = 10)
        {
            $params = [
                'index' => $index,
                'body'  => [
                    'from'  => $from,
                    'size'  => $size,
                    'query' => [
                        'match' => [
                            'class_name'  => '版',
                        ],
                    ]
                ],
            ];
    
            return $this->es->search($params);
        }
    
        /*
         * @Tile: 多功能搜索
         * @Param string $index 索引名称
         * @Param array $where 条件数组
         * @Param array $sort 排序数组
         * @Param int $from 开始查询的位置
         * @Param int $size 一共查询的条数
         * @Return array 查询结果
         * */
        public function query($index,$where,$sort='',$from=0,$size=1500)
        {
            $params = [
                "index" => $index,
                "body" => [
                    "from" => $from,
                    "size" => $size,
                    "query" => $where
                ]
            ];
    
            if($sort) {
                $params['body']['sort'] = $sort;
            }
    
            return $this->es->search($params);
        }
    
    
    
    }

    4. 业务使用代码块。

    以下app('es')在provider.php注册到容器中

    <?php
    namespace appadmincontroller;
    
    use appBaseController;
    
    class Test extends BaseController
    {
    	
        public function index()
        {
        	var_dump(2323);die;
        }
    
        // 测试ElasticSearch
        public function esTest()
        {
            $res = app('es')->info();
            dump($res);die;
        }
    
        // 创建一个索引
        public function createIndex()
        {
            $res = app('es')->index("goods");
            var_dump($res);die;
        }
    
        // 创建文档
        public function createDoc()
        {
    
            $goodsList = appcommonmodelGoods::page(0,1500)->select()->toArray();
    
            foreach ($goodsList as $val) {
                $res = app('es')->createDoc('goods',$val);
            }
    
            dump($res);die;
    
            $goods = appcommonmodelGoods::find(1);
            var_dump($goods);die;
        }
    
        // 搜索
        public function queryDoc()
        {
            // 获取所有
            $where = [
                'match_all' => new stdClass(),                 // 空对象,PHP5.3  或者     (object)[]    //也是给出空数组的方式
            ];
    
            // 单字段完全匹配
    //        $where = [
    //            'match_phrase' => [
    //                'class_name' => '班',
    //            ]
    //        ];
    
            // 单字段模糊匹配
    //        $where = [
    //            'match' => [
    //                'goods_name' => '苹果'
    //            ]
    //        ];
    
            // 多字段匹配
    //        $where = [
    //            'multi_match' => [
    //                'query' => '苹果',
    //                'fields' => ['goods_name'],     //这里添加多字段
    //                'type' => 'best_fields'         //most_fields多字段匹配更高,best_fields完全匹配占比更高
    //            ]
    //        ];
    
            // 联合搜索must联合必须,should联合可以,must_not联合不必须, 联合搜索类似SQL的多字段查询(就使用must)
    //        $where = [
    //            'bool' => [
    //                'must' => [
    //                    'match' => [
    //                        'goods_name' => '苹果'
    //                    ]
    //                ],
    //                'should' => [
    //                    'match' => [
    //                        'level' => '3'
    //                    ]
    //                ]
    //            ]
    //        ];
    
            // 排序非必填
            $sort = [
                "sort" => "asc"
            ];
    
            $res = app('es')->query('goods',$where,$sort,0,3000);
            dump($res);die;
    
    //        $res = app('es')->queryData('class','class_name',0,20);
    //        dump($res);die;
        }
    
        // 获取索引(索引中的某个文档)
        public function getDoc()
        {
            $res = app('es')->getIndex('goods',1500);
            dump($res);die;
        }
    
        // 获取的索引配置
        public function getIndexConfig()
        {
            $res = app('es')->getIndexConfig('class,user,goods');
            dump($res);die;
        }
    
    
        
    }
    

    示例源码,公众号回复"es"获取。

  • 相关阅读:
    75. Sort Colors
    101. Symmetric Tree
    121. Best Time to Buy and Sell Stock
    136. Single Number
    104. Maximum Depth of Binary Tree
    70. Climbing Stairs
    64. Minimum Path Sum
    62. Unique Paths
    css知识点3
    css知识点2
  • 原文地址:https://www.cnblogs.com/zerofc/p/12905015.html
Copyright © 2011-2022 走看看