thinkphp使用es7简单封装

简单封装一个es类(前提是已经安装好了es组件包)

<?php
namespace app\common\controller;


use Elasticsearch\ClientBuilder;
use Elasticsearch\Common\Exceptions\BadRequest400Exception;
use think\facade\Log;

/**
 * MySQL与 es 的参照对比
 * mysql              es
 * 数据库(database)      索引(indices)
 * 表(tables)          类型(types)
 * 行(rows)              文档(documents)
 * 字段(columns)      字段(fields)
 * Class ElasticSearch
 * @package app\common\controller
 */
class ElasticSearch
{
    private $client;

    private $host = [
        '192.168.111.130:9200'
    ];

    const INDEX = 'my_index';

    public function __construct()
    {
        $this->client = ClientBuilder::create()->setHosts($this->host)->build();
    }

    /**
     * 创建索引
     * 相当于数据库中建库建表的操作
     * @param string $index
     * @param array $body
     * @return bool
     */
    public function createIndex(string $index = 'my_index', array $body = []): bool
    {
        $params = [
            'index' => $index, //索引名称
            'body' => [
                'settings' => [ // 设置配置
                    'number_of_shards' => 1, //主分片数
                    'number_of_replicas' => 0 //主分片的副本数
                ],
                'mappings' => [  // 设置映射
                    '_source' => [   // 存储原始文档
                        'enabled' => 'true'
                    ],
                    'properties' => $body // 配置数据结构与类型
                ],
            ]
        ];

        try {
            $this->client->indices()->create($params);
        } catch (\Exception $e) {
            Log::write($e->getMessage(), "创建索引{$index}失败");
            return false;
        }

        return true;
    }

    /**
     * 删除索引(删除数据库)
     * @param string $index
     * @return bool
     */
    public function deleteIndex(string $index = self::INDEX): bool
    {
        $params = [
            'index' => $index
        ];

        try {
            $this->client->indices()->delete($params);
        } catch (\Exception $e) {
            Log::write($e->getMessage(), "删除索引{$index}失败");
            return false;
        }

        return true;
    }

    /**
     * 判断索引是否存在
     * @param string $index
     * @return bool
     */
    public function indexExists(string $index = self::INDEX): bool
    {
        $params = ['index' => $index];

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

    /**
     * 查看映射
     * @param string $index
     * @return array
     */
    public function getMapping(string $index = self::INDEX): array
    {
        $params = [
            'index' => $index,
        ];

        try {
            return $this->client->indices()->getMapping($params);
        } catch (\Exception $e) {
            return json_decode($e->getMessage(), true);
        }
    }

    /**
     * 添加文档(添加一行数据)
     * @param int $id
     * @param array $body
     * @param string $index
     * @return bool
     */
    public function addDos(int $id, array $body, string $index = self::INDEX): bool
    {
        $params = [
            'index' => $index,
            'id' => $id,
            'body' => $body
        ];

        try {
            $this->client->index($params);
        } catch (\Exception $e) {
            Log::write($e->getMessage(), "新增文档{$id}失败");
            return false;
        }

        return true;
    }

    /**
     * 批量插入文档
     * @param array $params
     * @return bool
     */
    public function addAllDos(array $params)
    {
        try {
            $this->client->bulk($params);
        } catch (\Exception $e) {
            Log::write($e->getMessage(), "分批插入失败");
            return false;
        }

        return true;
    }

    /**
     * 获取文档总数(统计)
     * @param string $index
     * @return array|mixed
     */
    public function getCountDos(string $index = self::INDEX)
    {
        $params = [
            'index' => $index,
        ];

        try {
            return $this->client->count($params);
        } catch (\Exception $e) {
            return json_decode($e->getMessage(), true);
        }
    }

    /**
     * 获取文档(获取一行数据)
     * @param int $id
     * @param string $index
     * @return array|mixed
     */
    public function getDoc(int $id, string $index = self::INDEX): array
    {
        $params = [
            'index' => $index,
            'id' => $id
        ];

        try {
            return $this->client->get($params);
        } catch (\Exception $e) {
            return json_decode($e->getMessage(), true);
        }
    }

    /**
     * 更新文档(更新一条数据)
     * @param int $id
     * @param array $body
     * @param string $index
     * @return bool
     */
    public function updateDoc(int $id, array $body, string $index = self::INDEX): bool
    {
        $params = [
            'index' => $index,
            'id' => $id,
            'body' => [
                'doc' => $body
            ]
        ];

        try {
            $this->client->update($params);
        } catch (\Exception $e) {
            Log::write($e->getMessage(), "更新文档{$id}失败");
            return false;
        }

        return true;
    }

    /**
     * 删除文档(删除一条数据)
     * @param int $id
     * @param string $index
     * @return bool
     */
    public function deleteDoc(int $id, string $index = self::INDEX): bool
    {
        $params = [
            'index' => $index,
            'id' => $id
        ];

        try {
            $this->client->delete($params);
        } catch (\Exception $e) {
            Log::write($e->getMessage(), "删除文档{$id}失败");
            return false;
        }

        return true;
    }

    /**
     * 搜索
     * @param string $keywords 检索词
     * @param string $index 索引名
     * @param int $limit 一次显示多少条
     * @param int $page 分页页码,从几开始
     * @return array
     */
    public function searchDoc(string $keywords, string $index = self::INDEX, int $limit = 10, int $page = 1): array
    {
        $offset = ((int)$page - 1) * (int)$limit;
        $params = [
            'index' => $index,
            'body' => [
                '_source' => ['id', 'title'], // 指定返回的字段
                'query' => [
                    // 多字段匹配
//                    'multi_match' => [
//                        'query' => $keywords,
//                        'fields' => ['title', 'content', 'keyword'],
//                        'type' => 'most_fields' // most_fields 多字段匹配度更高   best_fields  完全匹配占比更高
//                    ],
                    // 单个字段匹配
//                    'match' => [
//                        'title' => $keywords
//                    ],
                    // 完全匹配
//                    'match_phrase' => [
//                        'title' => $keywords
//                    ],
                    // 联合查询
                    'bool' => [
                        'should' => [ // 相当于or
                            [
                                'match_phrase' => [
                                    'title' => $keywords
                                ]
                            ],
                            [
                                'match_phrase' => [
                                    'content' => $keywords
                                ]
                            ],
                            [
                                'match_phrase' => [
                                    'keyword' => $keywords
                                ]
                            ],
                        ],
//                        'must' => [ // 相当于and
//                            [
//                                'match' => [
//                                    'title' => $keywords
//                                ]
//                            ],
//                        ],
//                        'should' => [ // 相当于or
//                            [
//                                'match' => [
//                                    'title' => $keywords
//                                ]
//                            ],
//                            [
//                                'match' => [
//                                    'content' => $keywords
//                                ]
//                            ],
//                            [
//                                'match' => [
//                                    'keyword' => $keywords
//                                ]
//                            ],
//                        ],
//                        'must_not' => [ // 相当于not
//                            [
//                                'match' => [
//                                    'content' => $keywords
//                                ]
//                            ]
//                        ],
//                        'filter' => [ // 过滤器  gt 大于;gte 大于等于;lt 小于;lte 小于等于
//                            'range' => [
//                                'id' => ['lt' => 20598, 'gt' => 20590]
//                            ]
//                        ],
                    ],
                ],
                'highlight' => [ // 搜索词高亮设置
//                    'pre_tags' => "<p class='key' style='color: red;'>", // 自定义高亮样式
//                    'post_tags' => "</p>",
                    'fields' => [ // 设置高亮的字段
                        'title' => (object)[],
                        'content' => (object)[],
                        'keyword' => (object)[],
                    ]
                ],
//                'sort' => [['id' => ['order' => 'desc']]], // 排序,不设置会根据最高匹配度来排序
                'from' => $offset, // 分页 - 从哪开始
                'size' => $limit // 一次显示多少条
            ]
        ];

        try {
            return $this->client->search($params);
        } catch (\Exception $e) {
            return json_decode($e->getMessage(), true);
        }
    }
}

然后就可以在要用到的地方调用了,这里只写一个测试方法

<?php

namespace app\index\controller;


use app\common\controller\ElasticSearch;
use app\index\model\Articles;
use think\App;
use think\Db;

class Es extends HomeBase
{
    private $es;
    private $index = 'article';

    public function __construct(App $app = null)
    {
        parent::__construct($app);
        $this->es = new ElasticSearch();
    }

    public function test()
    {
//        $this->es->deleteIndex('test_ik');
//         $this->create();
//          $map = $this->es->getMapping($this->index);
//          dump($map);
//         $this->add();
//         $this->get();
        $this->search('测试');
    }

    public function create()
    {
        if (!$this->es->indexExists($this->index)) {
            $params = [
                'id' => ['type' => 'integer'],
                'title' => ['type' => 'keyword'],
                'keyword' => ['type' => 'keyword'],
                'abstract' => ['type' => 'text'],
                'content' => ['type' => 'text'],
                'category_id' => ['type' => 'integer'],
                'cover_map' => ['type' => 'text'],
                'release_time' => ['type' => 'date'],
            ];
            $this->es->createIndex($this->index, $params);
        }
    }

    public function add()
    {
        $success = 0;
        $error = 0;
        $num = 500;
        Articles::where(['status' => 1, 'is_del' => 0])
            ->field('id,title,keyword,abstract,content,category_id,cover_map,release_time')
            ->chunk($num, function ($articles) use (&$success, &$error, $num) {
                $params = ['body' => []];
                foreach ($articles as $article) {
                    $params['body'][] = [
                        'index' => [   #创建或替换
                            '_index' => $this->index,
                            '_id' => $article['id'],
                        ],
                    ];
                    $params['body'][] = $article;
                }
                $res = $this->es->addAllDos($params);
                if ($res) {
                    $success += $num;
                } else {
                    $error += $num;
                }
            });
        echo "同步完成,成功{$success}条,失败{$error}条";
    }

    public function get()
    {
        $res = $this->es->getCountDos($this->index);
        dump($res);
    }

    public function search($keyword)
    {
        $res = $this->es->searchDoc($keyword, $this->index);
        dump($res);
    }
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容