thinkphp5 封装Elasticsearch工具类

<?php
/**
 * Created by PhpStorm.
 * Date: 2021/6/24
 * Time: 14:59
 */

namespace tools\es;


use Elasticsearch\ClientBuilder;
use traits\think\Instance;


class MyElasticsearch
{
    //ES客户端链接
    private $client;

    /*
     * 构造函数
     * 链接es
     */
    public function __construct()
    {
        $params = ['127.0.0.1:9200'];
        $this->client = ClientBuilder::create()->setHosts($params)->build();
    }
    /*
     * 判断索引是否存在
     * @$param string $index_name
     * @return bool|mixed|string
     */
    public function exists_index($index_name = 'test_ik')
    {
        $params = [
            'index' => $index_name
        ];
        try {
            return $this->client->indices()->exists($params);
        } catch (\Elasticsearch\Common\Exceptions\BadRequest400Exception $e) {
            $msg = $e->getMessage();
            $msg = json_decode($msg, true);
            return $msg;
        }
    }

    /*
     * 创建索引
     * @param string $index_name
     * @return array|mixed|string
     */
    public function create_index($index_name = 'test_index')
    {
        $params = [
            'index' => $index_name,
            'body' => [
                'settings' => [
                    'number_of_shards' => 5,
                    'number_of_replicas' => 0
                ]
            ]
        ];
        try {
            return $this->client->indices()->create($params);
        } catch (\Elasticsearch\Common\Exceptions\BadRequest400Exception $e) {
            $msg = $e->getMessage();
            $msg = json_decode($msg, true);
            return $msg;
        }
    }
    /*
     * 删除索引
     * @param string $index_name
     * @return array
     */
    public function delete_index($index_name = 'test_es')
    {
        $params = [
            'index' => $index_name
        ];
        try {
            return $this->client->indices()->delete($params);
        } catch (\Elasticsearch\Common\Exceptions\BadRequest400Exception $e) {
            $msg = $e->getMessage();
            $msg = json_decode($msg, true);
            return $msg;
        }
    }
    /*
     * 添加文档
     * $param $id
     * $param $doc ['id' => 100,'title' => 'iphone']
     * $param string $index_name
     * $param string $type_name
     * @return array
     */
    public function add_doc($id, $doc, $index_name = 'test_es', $type_name = 'goods')
    {
        //参数绑定
        $params = [
            'index' => $index_name,
            'type' => $type_name,
            'id' => $id,
            'body' => $doc
        ];
        //添加文档
        $response = $this->client->index($params);
        //返回数据
        return $response;
    }

    /*
     * 判断文档是否存在
     * @param int id
     * @param string $index_name
     * $param string $type_name
     * @param array|bool
     */
    public function exists_doc($id, $index_name, $type_name)
    {
        $params = [
            'id' => $id,
            'index_name' => $index_name,
            'type_name' => $type_name,
        ];
        $response = $this->client->exists($params);
        return $response;
    }
    /*
     * 获取文档内容
     * @param int $id
     * @param string $index_name
     * @param string $type_name
     * @return array
     */
    public function get_doc($id, $index_name, $type_name)
    {
        $params = [
            'id' => $id,
            'index_name' => $index_name,
            'type_name' => $type_name,
        ];
        $response = $this->client->get($params);
        return $response;
    }
    /*
     * 更新文档
     * @param int $id
     * @param string $index
     * @param string $type_name
     * @param array body ['doc' => ['title' => '商品的信息']]
     * @return array
     */
    public function update_doc($id, $index_name, $type_name, $body = [])
    {
        $params = [
            'id' => $id,
            'index_name' => $index_name,
            'type_name' => $type_name,
            'body' => $body,
        ];
        $response = $this->client->update($params);
    }
    /*
     * 删除文档
     * @param int $id
     * @param string $index_name
     * @param string type_name
     * @return array
     */
    public function del_doc($id, $index_name, $type_name)
    {
        $params = [
            'id' => $id,
            'index_name' => $index_name,
            'type_name' => $type_name,
        ];
        $response = $this->client->delete($params);
        return $response;
    }

    /*
     * 搜索文档(分页、权重、排序、过滤)
     * @param string $index_name
     * @param string $type_name
     * $params array $body
     * $body =[
            'query' => [
                'bool' => [
                    'should' =>[
                        [
                            'match' =>[
                                'cate_name' => [
                                    'query' => $keyword,
                                    'boost' => 4, //权重大
                                ]
                            ]
                        ],
                        [
                            'match' =>[
                                'goods_name' => [
                                    'query' => $keyword,
                                    'boost' => 3, //权重大
                                ]
                            ]
                        ],
                        [
                            'match' =>[
                                'goods_introduce' => [
                                    'query' => $keyword,
                                    'boost' => 2, //权重大
                                ]
                            ]
                        ],
                    ],
                ],
            ],
            'sort' => ['id' => ['order' => 'desc']],
            'from' => $from,
            'size' => $size
        ];
     * @return array
     */
    public function search_doc($index_name, $type_name, $body = [])
    {
        $params = [
            'index' => $index_name,
            'type'  => $type_name,
            'body'  => $body,
        ];
        $response = $this->client->search($params);
        return $response;
    }
}

ElasticSearch基本使用

节点与集群

Elastic 本质上是一个分布式数据库,允许多台服务器协同工作,每台服务器可以运行多个 Elastic 实例。

单个 Elastic 实例称为一个节点(node)。一组节点构成一个集群(cluster)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yDRjk7G1-1624800902177)(img/15356465131.png)]

索引

在Elasticsearch中存储数据的行为就叫做索引(indexing)

在Elasticsearch中,文档归属于一种类型(type),而这些类型存在于**索引(index)**中

类比传统关系型数据库:

Relational DB -> Databases -> Tables -> Rows -> Columns
Elasticsearch -> Indices   -> Types  -> Documents -> Fields

Elasticsearch集群可以包含多个索引(indices)(数据库)

每一个索引可以包含多个类型(types)(表)

每一个类型包含多个文档(documents)(行)

然后每个文档包含多个字段(Fields)(列)。

商品搜索功能

搜索规则

可根据关键词商品名称、商品介绍、商品分类进行全文搜索

创建商品全量索引

<?php

namespace app\cli\controller;

use think\Controller;
use think\Request;

class Es extends Controller
{
    /**
     * 创建商品索引并导入全部商品文档
     * cd public
     * php index.php /cli/Es/createAllGoodsDocs
     */
    public function createAllGoodsDocs()
    {
        try{
            //实例化ES工具类
            $es = new \tools\es\MyElasticsearch();
            //创建索引
            if($es->exists_index('goods_index')) $es->delete_index('goods_index');

            $es->create_index('goods_index');
            $i = 0;
            while(true){
                //查询商品数据 每次处理1000条
                $goods = \app\common\model\Goods::with('category')->field('id,goods_name,goods_desc, goods_price,goods_logo,cate_id')->limit($i, 1000)->select();
                if(empty($goods)){
                    //查询结果为空,则停止
                    break;
                }
                //添加文档
                foreach($goods as $v){
                    unset($v['cate_id']);
                    //调用封装的方法进行添加文档
                    $es->add_doc($v['id'],$v, 'goods_index', 'goods_type');
                }
                $i += 1000;
            }
            die('success');
        }catch (\Exception $e){
            $msg = $e->getMessage();
            die($msg);
        }
    }
}

在thinkphp的public目录下执行

php index.php /cli/Es/createAllGoodsDocs

将数据表中的数据存储到es中

控制器部分
public function index($id=0)
    {
        //接收参数
        $keywords = input('keywords');
        if(empty($keywords)){
            //获取指定分类下商品列表
            if(!preg_match('/^\d+$/', $id)){
                $this->error('参数错误');
            }
            //查询分类下的商品
            $list = \app\common\model\Goods::where('cate_id', $id)->order('id desc')->paginate(10);
            //查询分类名称
            $category_info = \app\common\model\Category::find($id);
            $cate_name = $category_info['cate_name'];
        }else{//进行全文索引查询
            try{
                //从ES中搜索
                $list = \app\home\logic\GoodsLogic::search();
                $cate_name = $keywords;
            }catch (\Exception $e){
                $this->error('服务器异常');
            }
        }
        return view('index', ['list' => $list, 'cate_name' => $cate_name]);
    }
搜索逻辑部分
<?php

namespace app\home\logic;

use think\Controller;

class GoodsLogic extends Controller
{
    public static function search(){
        //实例化ES工具类
        $es = new \tools\es\MyElasticsearch();
        //计算分页条件
        $keywords = input('keywords');
        $page = input('page', 1);
        $page = $page < 1 ? 1 : $page;
        $size = 10;
        $from = ($page - 1) * $size;
        //组装搜索参数体
        $body = [
            'query' => [
                'bool' => [
                    'should' => [
                        [ 'match' => [ 'cate_name' => [
                            'query' => $keywords,
                            'boost' => 4, // 权重大,优先查询cate_name
                        ]]],
                        [ 'match' => [ 'goods_name' => [
                            'query' => $keywords,
                            'boost' => 3,
                        ]]],
                        [ 'match' => [ 'goods_desc' => [
                            'query' => $keywords,
                            'boost' => 2,
                        ]]],
                    ],
                ],
            ],
            'sort' => ['id'=>['order'=>'desc']],
            //本页的第一条数据
            'from' => $from,
            //一页十行数据
            'size' => $size
        ];
        //进行搜索
        $results = $es->search_doc('goods_index', 'goods_type', $body);
        //获取数据
        $data = array_column($results['hits']['hits'], '_source');
        $total = $results['hits']['total']['value'];
        //分页处理
        $list = \tools\es\Espage::paginate($data, $size, $total);
        return $list;
    }
}

商品文档维护

在Goods商品模型中编写

新增商品后,在ES中添加商品文档

更新商品后,在ES中修改商品文档

删除商品后,在ES中删除商品文档

protected static function init()
    {
        //实例化ES工具类
        $es = new \tools\es\MyElasticsearch();
        //设置新增回调
        self::afterInsert(function($goods)use($es){
            //添加文档
            $doc = $goods->visible(['id', 'goods_name', 'goods_desc', 'goods_price'])->toArray();
            $doc['cate_name'] = $goods->category->cate_name;
            $es->add_doc($goods->id, $doc, 'goods_index', 'goods_type');
        });
        //设置更新回调
        self::afterUpdate(function($goods)use($es){
            //修改文档
            $doc = $goods->visible(['id', 'goods_name', 'goods_desc', 'goods_price', 'cate_name'])->toArray();
            $doc['cate_name'] = $goods->category->cate_name;
            $body = ['doc' => $doc];
            $es->update_doc($goods->id, 'goods_index', 'goods_type', $body);
        });
        //设置删除回调
        self::afterDelete(function($goods)use($es){
            //删除文档
            $es->delete_doc($goods->id, 'goods_index', 'goods_type');
        });
    }
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值