php Elasticsearch使用,Elasticsearch类,原创在用

php Elasticsearch使用,Elasticsearch类,原创在用

  • thinkphp5框架为例,composer下载es扩展到vender目录
  • 自己随便弄台服务器,安装es
  • 使用kibana来管理你的es数据库会很爽
  • 创建索引是注意自己的索引数组配置,es不像数据库一样,创建好表结构是不能改的,所以每次改结构都必须以版本的形式替换(比如第一版:shop_v1.0,改一次就再创建一个shop_v1.1)

先呈上es类:
我的目录结构是
/Users/smt/www/ups-api/extend/searchEngine/EsModel.php

<?php

namespace searchEngine;
use Elasticsearch\ClientBuilder;

/**
 * ES 操作类
 *
 * mysql 中的数据库 对应 ES 中的 index:索引
 * mysql 中的数据表 对应 ES 中的 type:类型
 * mysql 中的记录行 对应 ES 中的 Document:文档
 * mysql 中的表结构 对应 ES 中的 Mapping :文档模板
 * Class Elasticsearch
 *
 */
class EsModel
{

    private $client;
    public $index_name;
    private $es_host;
    private $es_username;
    private $es_password;

    /**
     * 构造函数
     * EsModel constructor.
     */
    public function __construct( $host='', $index='', $user='', $pass='' )
    {
        // 地址:端口
        $this->es_host = empty($host) ? config('es_conf.es_host') . ':' . config('es_conf.es_port') : $host;
        // 默认数据库 - darlar_test
        $this->index_name = empty($index) ? config('es_conf.es_index') : $index;
        // username
        $this->es_username = empty($user) ? config('es_conf.es_username') : $user;
        // password
        $this->es_password = empty($pass) ? config('es_conf.es_password') : $pass;

        $params  = [ $this->es_host ];
        $this->client = ClientBuilder::create()->setBasicAuthentication($this->es_username,$this->es_password)->setHosts($params)->build();
    }

    /**
     * Explain: 测试方法
     * User: smt \(^o^)/~
     * Date: 2020-09-15 20:39
     */
    public function index()
    {
        $docs   = [];
        $docs[] = ['fid' => '1', 'name' => '小明', 'profile' => '我做的ui界面强无敌。', 'score' => 120];
        $docs[] = ['fid' => '2', 'name' => '小张', 'profile' => '我的php代码无懈可击。', 'score' => 50];
        $docs[] = ['fid' => '3', 'name' => '小杨', 'profile' => '为所欲为,不行就删库跑路。', 'score' => 89];

        foreach ($docs as $k => $v) {
            $r = $this->addDoc($v['fid'], $v);   //3.添加文档
        }

        $keywords = "删库 别烦我";

        $body = [
            'query' => [
                'bool' => [
                    'should' => [
                        ['match' => ['profile' => [
                            'query' => $keywords,
                            'boost' => 3, // 权重大
                        ]]],
                        ['match' => ['name' => [
                            'query' => $keywords,
                            'boost' => 2,
                        ]]],
                    ],
                ],
            ],
            'sort' => ['score'=>['order'=>'desc']]
            // , 'from' => $from, 'size' => $size
        ];
        $r    = $this->searchDoc($body);  //4.搜索结果
        dump($r);die;
    }

    /**
     * Explain: 创建索引 - 创建数据库
     * @param string $index_name
     * @return array|mixed|string
     * User: smt \(^o^)/~
     * Date: 2020-09-15 20:41
     */
    public function createIndex($index_name = '')
    {
        if (empty($index_name)) return false;

        // 只能创建一次
        $params = [
            'index' => $index_name,
            'body'  => [
                'settings'=>[
                    'number_of_shards'   => 3,
                    'number_of_replicas' => 0,
                    'analysis'           => [
                        'tokenizer' => ['comma' => ['type' => 'pattern', 'pattern' => ',']],
                        'analyzer'  => ['comma' => ['type' => 'custom', 'tokenizer' => 'comma']]
                    ]
                ],
                'mappings'=>[
                    'properties' => [
                        'fid'                     => ['type' => 'integer'], // 搭配id
                        'fsku'                    => ['type' => 'keyword'], // 搭配编码
                        'fcate_id'                => ['type' => 'text', 'analyzer' => 'comma', 'search_analyzer' => 'comma'], // 搭配分类id
                        'fimage'                  => ['type' => 'keyword'],                                                    // 搭配封面
                        'ftag'                    => ['type' => 'text', 'analyzer' => 'comma', 'search_analyzer' => 'comma'],    // 标签,搜索关键词
                        'season'                  => ['type' => 'text', 'analyzer' => 'comma', 'search_analyzer' => 'comma'], // 季节
                        'fname'                   => ['type' => 'text', 'analyzer' => 'ik_max_word', 'search_analyzer' => 'ik_max_word'], // 搭配名称
                        'fname_standard'          => ['type' => 'text', 'analyzer' => 'standard', 'search_analyzer' => 'standard'], // 搭配名称
                        'fproduct_prices'         => ['type' => 'float'], // 搭配原价
                        'fprice'                  => ['type' => 'float'], // 折扣价
                        'add_time'                => ['type' => 'long'], // 添加时间
                        'is_show'                 => ['type' => 'integer'], // 是否上架
                        'fdid'                    => ['type' => 'integer'], // 搭配师id
                        'sort'                    => ['type' => 'integer'], // 排序
                        'goods_type'              => ['type' => 'integer'], // 男装女装分类
                        'sale_count'              => ['type' => 'integer'], // 销量
                        'is_hot'                  => ['type' => 'integer'], // 热门推荐:是(1),否(0)
                        'top_new_id'              => ['type' => 'integer'], // 上新类型id
                        'new_time'                => ['type' => 'long'], // 上新时间
                        'is_del'                  => ['type' => 'integer'], // 是否删除 1是,0否
                        'height_start'            => ['type' => 'integer'], // 最低身高
                        'height_end'              => ['type' => 'integer'], // 最高身高
                        'weight_start'            => ['type' => 'integer'], // 最小体重
                        'weight_end'              => ['type' => 'integer'], // 最大体重
                        'uid'                     => ['type' => 'long'], // 创建人id
                        'up_time'                 => ['type' => 'long'], // 更新时间
                        'crowd_classify_str'      => ['type' => 'text','analyzer' => 'comma', 'search_analyzer' => 'comma'], // 人群
                        'preference_classify_str' => ['type' => 'text','analyzer' => 'comma', 'search_analyzer' => 'comma'], // 偏好
                        'style_classify_str'      => ['type' => 'text','analyzer' => 'comma', 'search_analyzer' => 'comma'], // 风格
                        'scene_classify_str'      => ['type' => 'text','analyzer' => 'comma', 'search_analyzer' => 'comma'], // 场景
                        'grounding_time'          => ['type' => 'long'], // 上架时间
                        'special_id_str'          => ['type' => 'text', 'analyzer' => 'comma', 'search_analyzer' => 'comma'], // 专题id
                        'body_shape'              => ['type' => 'text','analyzer' => 'comma', 'search_analyzer' => 'comma'], // 身型
                        'fdid_username'           => ['type' => 'keyword'], // 搭配师
                        'uid_name'                => ['type' => 'keyword'], // 创建人
                        'cover_width'             => ['type' => 'integer'], // 封面宽度
                        'cover_height'            => ['type' => 'integer'], // 封面高度
                        'kol_fprice'              => ['type' => 'float'], // kol折扣价
                        'discount'                => ['type' => 'float'], // 折扣比例
                        'size_str'                => ['type' => 'text', 'analyzer' => 'comma', 'search_analyzer' => 'comma'], // 各个规格尺码
                        'colour_str'              => ['type' => 'text', 'analyzer' => 'comma', 'search_analyzer' => 'comma'], // 各个规格颜色
                    ]
                ]
            ]
        ];

        try {
            return $this->client->indices()->create($params);
        } catch (Elasticsearch\Common\Exceptions\BadRequest400Exception $e) {
            $msg = $e->getMessage();
            $msg = json_decode($msg, true);
            return $msg;
        }
    }

    /**
     * Explain: 删除索引 - 删除数据库
     * @param string $index_name 索引名称(数据库)
     * @return array
     * User: smt \(^o^)/~
     * Date: 2020-09-15 20:42
     */
    public function deleteIndex($index_name = '')
    {
        if (empty($index_name)) return false;

        $params = ['index' => $index_name];

        try {
            $response = $this->client->indices()->delete($params);
            return $response;
        } catch (Elasticsearch\Common\Exceptions\BadRequest400Exception $e) {
            $msg = $e->getMessage();
            $msg = json_decode($msg, true);
            return $msg;
        }
    }


    /**
     * Explain: 创建文档模板 - 创建表结构
     * @param array $params 参数
     * @return array
     * User: smt \(^o^)/~
     * Date: 2020-09-15 20:43
     */
    public function createMappings($params)
    {
        try {
            $response = $this->client->indices()->putMapping($params);
            return $response;
        } catch (Elasticsearch\Common\Exceptions\BadRequest400Exception $e) {
            $msg = $e->getMessage();
            $msg = json_decode($msg, true);
            return $msg;
        }
    }

    /**
     * Explain: 查看映射
     * @param string $index_name
     * @return array
     * User: smt \(^o^)/~
     * Date: 2020-09-15 20:46
     */
    public function getMapping( $index_name = '')
    {
        if (empty($index_name)) $index_name = $this->index_name;

        $params   = [
            'index' => $index_name,
        ];
        $response = $this->client->indices()->getMapping($params);
        return $response;
    }


    /**
     * 添加新字段
     * author: jason
     * @param $fieldName    字段名  :name
     * @param $fieldParam  字段参数 :['type'=>'text','analyzer'=>'comma','search_analyzer'=>'comma']
     * @return array
     */
    public function addField($fieldName, $fieldParam)
    {
        $index = $this->index_name;
        $params = [
            'index' => $index,
            'body'  => [
                'properties' => [
                    $fieldName => $fieldParam
                ]
            ],
        ];
        return $this->client->indices()->putMapping($params);
    }

    /**
     * Explain: 添加文档
     * @param $_id 文档id
     * @param $data 要添加的数据
     * @param string $index_name
     * @return array
     * User: smt \(^o^)/~
     * Date: 2020-09-15 20:46
     */
    public function addDoc($_id = 0, $data = [], $index_name = '')
    {
        if (empty($_id)) return false;
        if (empty($data)) return false;

        if (empty($index_name)) $index_name = $this->index_name;

        $params = [
            'index' => $index_name,
            'id'    => $_id,
            'body'  => $data
        ];

        $response = $this->client->index($params);
        return $response;
    }

    /**
     * Explain: 判断文档存在
     * @param int $id
     * @param string $index_name
     * @return bool
     * User: smt \(^o^)/~
     * Date: 2020-09-15 20:47
     */
    public function existsDoc($id = 0, $index_name = '')
    {
        if (empty($id)) return false;

        if (empty($index_name)) $index_name = $this->index_name;

        $params = [
            'index' => $index_name,
            'id'    => $id
        ];

        $response = $this->client->exists($params);
        return $response;
    }


    /**
     * Explain: 获取文档
     * @param int $id
     * @param string $index_name
     * @return array
     * User: smt \(^o^)/~
     * Date: 2020-09-15 20:48
     */
    public function getDoc($id = 0, $index_name = '')
    {
        if (!$id) return false;

        if (empty($index_name)) $index_name = $this->index_name;

        $params = [
            'index' => $index_name,
            'id'    => $id
        ];

        $response = $this->client->get($params);
        return $response;
    }

    /**
     * Explain: 更新文档
     * @param int $id
     * @param array $data 要更新的数据
     * @param string $index_name
     * @return array
     * User: smt \(^o^)/~
     * Date: 2020-09-15 20:48
     */
    public function updateDoc($id = 0,$data = [], $index_name = '')
    {
        if (empty($id)) return false;

        if (empty($index_name)) $index_name = $this->index_name;

        // 可以灵活添加新字段,最好不要乱添加
        $params = [
            'index' => $index_name,
            'id'    => $id,
            'body'  => [
                'doc' => $data
            ]
        ];

        $response = $this->client->update($params);
        return $response;
    }

    /**
     * Explain: 删除文档
     * @param int $id
     * @param string $index_name
     * @return array
     * User: smt \(^o^)/~
     * Date: 2020-09-15 20:48
     */
    public function deleteDoc($id = 0, $index_name = '')
    {
        if (empty($id)) return false;

        if (empty($index_name)) $index_name = $this->index_name;

        $params = [
            'index' => $index_name,
            'id'    => $id
        ];

        $response = $this->client->delete($params);
        return $response;
    }

    /**
     * Explain: 查询文档 (分页,排序,权重,过滤)
     * @param string $index_name
     * @param array $body
     * @return array
     * User: smt \(^o^)/~
     * Date: 2020-09-15 20:48
     */
    public function searchDoc($body = [],$index_name = '')
    {
        if (empty($index_name)) $index_name = $this->index_name;
        $params = [
            'index' => $index_name,
            'body'  => $body
        ];
        $results = $this->client->search($params);
        return $results;
    }

    /**
     * Explain: 批量操作文档
     * @param $params
     * @return array
     * User: smt \(^o^)/~
     * Date: 2020-09-18 19:55
     */
    public function bulkDoc($params){
        $results = $this->client->bulk($params);
        return $results;
    }

}

基本使用:



    /**
     * Explain: 批量同步搭配商品到es 每天20分钟执行一次
     * User: smt \(^o^)/~
     * Date: 2020-09-17 20:53
     * php think essync batchSyncFullToes
     */
    public function batchSyncFullToes()
    {
        $FullModel = new StoreFull();
        // 校验es连通性
        $is_connect = checkElasticIsConnectionFail(2,0);
        if (empty($is_connect)) exit('es_error');

        // 实例化es
        $esModel = new EsModel();
        $index_name = $esModel->index_name; // 索引名称

//        $esModel      = new EsModel('xxx.xxx.xxx.xxx:9200','test_02','darlar_es','xxxxxxxx');

//        $idd = $esModel->existsDoc('XJ2020083596',$index_name); // 查询文档是否存在
//        dump($idd);die;

        // 删除库
//        $re = $esModel->deleteIndex($index_name);
//        dump($re);die;
        // 创建库
//        $re = $esModel->createIndex($index_name);
//        dump($re);die;

        ignore_user_abort();//关掉浏览器,PHP脚本也可以继续执行.
        set_time_limit(0);
        ini_set('memory_limit', '500M');
        ob_start();//打开缓冲区
        // 记录时间
        $start_time = date('Y-m-d H:i:s');
        echo "start_time ~  $start_time \n";
        $time_start = microtime(true); // 计算耗时
        ob_flush();flush();// 刷新缓冲区

        $page_size  = 50; // 每页条数
        $where      = [
            'is_del'  => 0,
            'is_show' => 1,// 已上架的搭配
            'fsku'    => ['neq', '']
        ];
        $total      = $FullModel->where($where)->field('fsku,count(fsku) as num ')->group('fsku desc')->count(); //总条数
        $total_page = ceil($total / $page_size); // 总页数
        $sum        = 0;

        echo "total: ~  $total \n";
        ob_flush();flush();// 刷新缓冲区

        // 取参数
        $condition = ElasticService::getParams(1);
        $condition['is_show'] = 1;

        for ($i = 1; $i <= $total_page; $i++) {
            $offset    = ($i - 1) * $page_size;
            $storeFull = $FullModel->where($where)->field('fsku,count(fsku) as num ')->group('fsku desc')->limit($offset, $page_size)->select()->toArray();
            if (empty($storeFull)) {
                break;
            } else {
                // 批量格式化搭配数据
                $data           = ElasticService::formatFull($storeFull, $condition);

                $params['body'] = [];
                foreach ($data as $key => $val) {
                    $params['body'][] = [
                        'index' => [   #创建或替换
                               '_index' => $index_name,
                               '_id'    => $val['fsku'],
                        ]
                    ];
                    $params['body'][] = $val;
                    $sum++;
                }
                $res = $esModel->bulkDoc($params);
                // 判断异常
                if ( !isset($res['errors']) || $res['errors'] !== false ) {
                    add_debug_log($res, 'batchSyncFullToes', '批量同步搭配数据到ES出错');
                    echo 'add_error_' . $i; exit();
                }
            }

            // 输出数量
            if ($sum > 0) echo "add_total:$sum ~ " . date('Y-m-d H:i:s') . " \n";

            ob_flush();flush();// 刷新缓冲区

//            sleep(1); // 暂停数秒
        }

        $end_time = date('Y-m-d H:i:s');
        echo "end_time ~  $end_time \n";
        ob_flush();flush();// 刷新缓冲区
        // 统计耗时
        $time_end = microtime(true);
        $time     = $time_end - $time_start;
        exit('add ok ~ add_total: ' . $sum . ', time:' . $time);
    }


end

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
PHP 使用 ElasticSearch 进行商品搜索的最佳实践如下: 1. 安装 ElasticSearchElasticsearch-PHP 客户端库 要使用 ElasticSearch 进行搜索,首先需要安装 ElasticSearchElasticsearch-PHP 客户端库。可以使用 Composer 来安装 Elasticsearch-PHP 客户端库,例如:composer require elasticsearch/elasticsearch。 2. 创建索引 在 ElasticSearch ,需要先创建一个索引,然后在该索引创建一个或多个型(type),最后将文档(document)添加到。在 PHP ,可以使用 Elasticsearch-PHP 客户端库来创建索引,例如:$client->indices()->create(['index' => 'my_index'])。 3. 添加文档 在 PHP 使用 Elasticsearch-PHP 客户端库,可以使用 $client->index() 方法来添加文档到指定的,例如:$client->index(['index' => 'my_index', 'type' => 'my_type', 'id' => 1, 'body' => ['name' => 'product1', 'price' => 10]])。 4. 进行搜索 在 PHP 使用 Elasticsearch-PHP 客户端库进行搜索,可以使用 $client->search() 方法。例如,要搜索名称为“product1”的商品,可以使用以下代码: ``` $params = [ 'index' => 'my_index', 'type' => 'my_type', 'body' => [ 'query' => [ 'match' => [ 'name' => 'product1' ] ] ] ]; $response = $client->search($params); ``` 以上就是在 PHP 使用 ElasticSearch 进行商品搜索的最佳实践。当然,还有很多其他的高级搜索技巧,例如使用聚合(aggregation)来计算平均价格、最高价格等等。可以根据具体的需求来逐步深入学习。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

布尼卡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值