php+es实现全文检索demo

1.首先确保本机有es环境

2.当前es是启动状态

3.当前composer添加了es扩展

 

控制器调用层:

<?php


namespace app\api\controller\v1;

use app\api\middleware\Token as TokenMiddleware;
use app\BaseController;
use app\lib\elasticsearch\Elasticsearch;

class Es extends BaseController
{
    protected $middleware = [TokenMiddleware::class => ['except' => ['index', 'search', 'update']]];

    /**
     * 添加ES索引
     * @return string
     */
    public function index()
    {
        $elasticsearch = new Elasticsearch();
        if ($elasticsearch->index()) {
            return json(['code' => 1000]);
        }
        return json(['code' => 1002]);
    }

    /**
     * 搜索ES关键词
     * @return string
     */
    public function search()
    {
        $elasticsearch = new Elasticsearch();
        $keyword = input('keyword');
        if ($result = $elasticsearch->search($keyword)) {
            return json(['code' => 1000, 'data' => $result]);
        }
        return json(['code' => 1002, 'data' => []]);
    }

    /**
     * 更新ES单条数据
     * @return string
     */
    public function update()
    {
        $elasticsearch = new Elasticsearch();
        $update = ['id' => 1, 'name' => 'isCheney', 'profile' => 'The bald blame', 'age' => 18];
        if ($elasticsearch->updateEs(1, $update)) {
            return json(['code' => 1000]);
        }
        return json(['code' => 1002]);
    }
}

封装的ES处理层:

<?php


namespace app\lib\elasticsearch;

use Elasticsearch\ClientBuilder;

/**
 * ES操作类
 * Class Elasticsearch
 * @package app\lib\elasticsearch
 */
class Elasticsearch extends Model
{
    private $client;

    /**
     * 构造函数
     * Elasticsearch constructor.
     */
    public function __construct()
    {
        $elasticsearchConfig = env('elasticsearch.host', '127.0.0.1') . ':' . env('elasticsearch.port', '9200');
        $params = [$elasticsearchConfig];
        $this->client = ClientBuilder::create()->setHosts($params)->build();
    }

    /**
     * 创建索引
     */
    public function index()
    {
        //第一次执行先屏蔽下面的删除索引方法,因为如果没有找到索引会报错
        $this->delete_index();
        //1.创建索引,索引就是数据库中的数据库概念
        $this->create_index();
        //2.创建文档模板,这个就是数据库中的表的概念
        $this->create_mappings();
        $this->get_mapping();
        $docs = [];
        $docs[] = ['id' => 1, 'name' => 'Charles', 'profile' => 'However, one strange enough, no one has ever seen the jaguar prey on the cattle and sheep', 'age' => 23];
        $docs[] = ['id' => 2, 'name' => 'Mark', 'profile' => 'Some people thought that the jaguar felt toolonely', 'age' => 24];
        $docs[] = ['id' => 3, 'name' => 'Bill', 'profile' => 'It is normal for the jaguar to be lazy in this environment', 'age' => 29];
        $docs[] = ['id' => 4, 'name' => 'Vincent', 'profile' => 'Others all agreed with him and put five panthers into the jaguar territory', 'age' => 26];
        $docs[] = ['id' => 5, 'name' => 'Joseph', 'profile' => 'one this principle does not only apply to animals, but also apply to human beings', 'age' => 21];
        $docs[] = ['id' => 6, 'name' => 'Linda', 'profile' => ' It is fairly common that disadvantages will turn into advantages and misfortunes into fortunes!', 'age' => 25];
        $docs[] = ['id' => 7, 'name' => 'William', 'profile' => 'one creature without any rivals is a lifeless creature', 'age' => 27];
        foreach ($docs as $k => $v) {
            $this->add_doc($v['id'], $v);   //3.添加文档
        }
        return true;
    }

    /**
     * 搜索ES结果
     * @param $keyword
     * @return mixed
     */
    public function search($keyword)
    {
        $res = $this->search_doc($keyword);  //4.搜索结果
        return $res['hits']['hits'];
    }

    /**
     * 根据id更新单条ES数据
     * @param $id
     * @param array $data
     * @param string $type_name
     * @param string $index_name
     * @return bool|mixed
     */
    public function updateEs($id, $data = [], $type_name = 'users', $index_name = 'cheney')
    {
        if (empty($id) || empty($data)) {
            return false;
        }
        $update = [
            'index' => $index_name,
            'type' => $type_name,
            'id' => $id,
            'body' => [
                'doc' => $data
            ]
        ];
        $res = $this->client->update($update);
        return $res['result'];
    }


    /**
     * 创建索引
     * @param string $index_name
     * @return array
     */
    public function create_index($index_name = 'cheney')
    {
        // 只能创建一次
        $params = [
            'index' => $index_name,
            'body' => [
                'settings' => [
                    'number_of_shards' => 1,
                    'number_of_replicas' => 0
                ]
            ],
        ];
        return $this->client->indices()->create($params);
    }

    /**
     * 删除索引
     * @param string $index_name
     * @return array
     */
    public function delete_index($index_name = 'cheney')
    {
        $params = ['index' => $index_name];
        return $this->client->indices()->delete($params);
    }

    /**
     * 创建文档模板
     * @param string $type_name
     * @param string $index_name
     * @return array
     */
    public function create_mappings($type_name = 'users', $index_name = 'cheney')
    {
        $params = [
            'index' => $index_name,//这里是索引名,相当于数据库名
            'type' => $type_name,//这里是类型名,相当于表名
            'body' => [
                //下面是数据类型定义,相当于数据库字段
                'properties' => [
                    'id' => [
                        'type' => 'long', // 整型
                        'index' => 'false', // 非全文搜索
                    ],
                    'name' => [
                        'type' => 'text', // 字符串型
                        'index' => 'true', // 全文搜索
                        'analyzer' => 'stop'
                    ],
                    'profile' => [
                        'type' => 'text',// 字符串型
                        'index' => 'true', // 全文搜索
                        'analyzer' => 'stop'
                    ],
                    'age' => [
                        'type' => 'integer',
                        'index' => 'false', //非 全文搜索
                    ],
                ]
            ]
        ];
        return $this->client->indices()->putMapping($params);
    }

    /**
     * 查看映射,就是相当于数据库的数据结构
     * @param string $type_name
     * @param string $index_name
     * @return array
     */
    public function get_mapping($type_name = 'users', $index_name = 'cheney')
    {
        $params = [
            'index' => $index_name,
            'type' => $type_name,
        ];
        return $this->client->indices()->getMapping($params);
    }

    /**
     * 添加文档
     * @param $id
     * @param $doc
     * @param string $index_name
     * @param string $type_name
     * @return array
     */
    public function add_doc($id, $doc, $index_name = 'cheney', $type_name = 'users')
    {
        $params = [
            'index' => $index_name,
            'type' => $type_name,
            'id' => $id,
            'body' => $doc
        ];
        return $this->client->index($params);
    }

    /**
     * 判断文档存在
     * @param int $id
     * @param string $index_name
     * @param string $type_name
     * @return bool
     */
    public function exists_doc($id = 1, $index_name = 'cheney', $type_name = 'users')
    {
        $params = [
            'index' => $index_name,
            'type' => $type_name,
            'id' => $id
        ];
        return $this->client->exists($params);
    }


    /**
     * 获取文档
     * @param int $id
     * @param string $index_name
     * @param string $type_name
     * @return array
     */
    public function get_doc($id = 1, $index_name = 'cheney', $type_name = 'users')
    {
        $params = [
            'index' => $index_name,
            'type' => $type_name,
            'id' => $id
        ];
        return $this->client->get($params);
    }

    /**
     * 更新文档
     * @param int $id
     * @param string $index_name
     * @param string $type_name
     * @return array
     */
    public function update_doc($id = 1, $index_name = 'cheney', $type_name = 'users')
    {
        // 可以灵活添加新字段,最好不要乱添加
        $params = [
            'index' => $index_name,
            'type' => $type_name,
            'id' => $id,
            'body' => [
                'doc' => [
                    'name' => '大王'
                ]
            ]
        ];
        return $this->client->update($params);
    }

    /**
     * 删除文档
     * @param int $id
     * @param string $index_name
     * @param string $type_name
     * @return array
     */
    public function delete_doc($id = 1, $index_name = 'cheney', $type_name = 'users')
    {
        $params = [
            'index' => $index_name,
            'type' => $type_name,
            'id' => $id
        ];
        return $this->client->delete($params);
    }

    /**
     * 查询文档 (分页,排序,权重,过滤)
     * @param string $keywords
     * @param string $index_name
     * @param string $type_name
     * @param int $from
     * @param int $size
     * @return array
     */
    public function search_doc($keywords = "good", $index_name = "cheney", $type_name = "users", $from = 0, $size = 10)
    {
        $params = [
            'index' => $index_name,
            'type' => $type_name,
            'body' => [
                'query' => [
                    //bool查询,可以把很多小的查询组成一个更为复杂的查询,
                    'bool' => [
                        // 这里should是查询profile字段包含$keywords关键词或者name字段包含$keywords关键词的文档。可以改为"must"意思是同时包含。must_not排除包含
                        'should' => [[
                            'match' => [
                                'profile' => [
                                    'query' => $keywords,
                                    'boost' => 3, // 权重大
                                ]]], [
                            'match' => [
                                'name' => [
                                    'query' => $keywords,
                                    'boost' => 2,
                                ]
                            ]],
                        ],
                    ],
                ],
                'sort' => [
                    'age' => ['order' => 'desc']
                ],
                'from' => $from,
                'size' => $size
            ]
        ];
        return $this->client->search($params);
    }
}

查看postman调用状态

1.新加入索引

 

返回1000说明加入索引和数据成功,为什么会有数据,看代码里面写的死数据

2.查询关键词

 

这里可以看到我们查询关键词“one”已经成功并且从es里面返回了数据

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值