Elasticsearch实例操作

前提条件本机运行了elasticsearch服务

安装Elasticsearch php插件
composer require elasticsearch/elasticsearch
基本的新增、删除索引
//加载Elasticsearch php插件
require "vendor/autoload.php";

use \Elasticsearch\ClientBuilder;

//本机host
$hosts = [
    '127.0.0.1:9200'
];
//连接
$client = ClientBuilder::create()->setHosts($hosts)->build();

$params = [
    //索引名
    'index' => 'artlce',
    'body' => [
        'settings' => [
            //分区数
            'number_of_shards' => 5,
            //副本数
            'number_of_replicas' => 1
        ],
        'mappings' => [
            //文档
            '_doc' => [
                '_source' => [
                    'enabled' => true
                ],
                'properties' => [
                    //文档的字段以及字段的类型
                    'anchor' => [
                        //keyword类型的字段只能通过精确值搜索到
                        'type' => 'keyword'
                    ],
                    'title' => [
                  		'type' => 'text',
                        //ik分词器的ik_max_word模式
                        'analyzer' => 'ik_max_word',
                        'search_analyzer' => 'ik_max_word'
                    ],
                    'desn' => [
                        'type' => 'text',
                        //ik分词器的ik_max_word模式
                        'analyzer' => 'ik_max_word',
                        'search_analyzer' => 'ik_max_word'
                    ]
                ]
            ]
        ]
    ]
];
// 创建索引
$response = $client->indices()->create($params);


//删除索引
$params1 = ['index' => 'artlce'];
$response1 = $client->indices()->delete($params1);
ik分词器

1、ik_max_word: 会将文本做最细粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,中华人民, 中华,华人,人民共和国,人民,人,民,共和国,共和,和国,国歌”,会穷尽各种可能的组合;

2、ik_smart: 会做最粗粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民,共和国,国歌”。 索引时,为了提供索引的覆盖范围,通常会采用ik_max_word分析器,会以最细粒度分词索引,搜索时为了提高搜索准确度,会采用ik_smart分析器,会以粗粒度分词

创建索引成功

在这里插入图片描述

基本的文档的操作
//加载Elasticsearch php插件
require "vendor/autoload.php";

use \Elasticsearch\ClientBuilder;

//本机host
$hosts = [
    '127.0.0.1:9200'
];
//连接
$client = ClientBuilder::create()->setHosts($hosts)->build();
//新增文档到索引中
$params2 = [
    //索引
    'index' => 'artlce',
    //类型 es6之后一个索引对应一个type
    'type' => '_doc',
    //文档id
    'id' => 1,
    //字段值
    'body' => [
        'anchor' => 'wyq',
        'title' => '这是一篇文章',
        'desn' => '这是一篇文章的简介',
    ],
];
$response = $client->index($params2);


//修改指定索引指定文档的内容
$params3 = [
    //索引
    'index' => 'artlce',
    //类型 es6之后一个索引对应一个type
    'type' => '_doc',
    //文档id
    'id' => 1,
    //字段值
    'body' => [
        'anchor' => 'wyq123',
    ],
];
$response = $client->update($params3);

//删除指定索引的文档
$params3 = [
    //索引
    'index' => 'artlce',
    //文档id
    'id' => 1,
];
$response = $client->delete($params3);


//查询索引文档的内容
$params4 = [
    'index' => "artcle",
    'body' => [
        'query' => [
            'match' => [
                'title' => "这是一篇"
            ]
        ]
    ]
];
$response = $this->client->search($params4);

在这里插入图片描述

在这里插入图片描述

集成到CI框架中

和之前的redis一样封装一个类,里面编写一些经常用到的Elasticsearch方法,之前在thinkphp5框架中封装过。

//libraries目录下的es类
<?php
/**
 * Created by PhpStorm.
 * User: wyq
 * Date: 2021/12/17
 * Time: 14:29
 */

require "vendor/autoload.php";

use \Elasticsearch\ClientBuilder;
use Elasticsearch\Common\Exceptions\BadRequest400Exception;
use Elasticsearch\Common\Exceptions\Missing404Exception;

//封装es工具类
class ES
{
    private $client = [];

    //构造函数中连接Es
    public function __construct()
    {
        $this->client = ClientBuilder::create()->setHosts(config_item('esHost'))->build();
    }

    public function getEs()
    {
        return $this->client;
    }

    /**
     * 创建索引
     * @param string $indexName 索引名
     * @param int $number_of_shards 分区数
     * @param int $number_of_replicas 副本数
     * @param array $data 字段数组
     * @return array
     */
    public function createIndex($indexName = "", $number_of_shards = 5, $number_of_replicas = 1, $data = [])
    {
        // 创建索引
        $params = [
            'index' => $indexName,
            'body' => [
                'settings' => [
                    'number_of_shards' => $number_of_shards,
                    'number_of_replicas' => $number_of_replicas
                ],
                'mappings' => [
                    '_doc' => [
                        '_source' => [
                            'enabled' => true
                        ],
                        'properties' => $data
                    ]
                ]
            ]
        ];
        try {
            $response = $this->client->indices()->create($params);
            $res = [
                'code' => 200,
                'message' => "success",
                'data' => $response
            ];
        } catch (BadRequest400Exception $exception) {
            $res = [
                'code' => $exception->getCode(),
                'message' => json_decode($exception->getMessage(), true),
                'data' => [],
            ];
        }
        return $res;
    }

    /**
     * 删除索引
     * @param string $indexName 索引名
     */
    public function delIndex($indexName = "")
    {
        $data = ['index' => $indexName];
        try {
            $response = $this->client->indices()->delete($data);
            $res = [
                'code' => 200,
                'message' => "success",
                'data' => $response
            ];
        } catch (Missing404Exception $exception) {
            $res = [
                'code' => $exception->getCode(),
                'message' => json_decode($exception->getMessage(), true),
                'data' => [],
            ];
        }
        return $res;
    }

    /**
     * 保存doc
     * @param string $indexName 索引名
     * @param int $id 新增、修改的文档id
     * @param array $data 新增、修改的文档数据
     */
    public function SaveDoc($indexName = "", int $id, $data = [])
    {
        // 写文档
        $params = [
            'index' => $indexName,
            'type' => '_doc',
            'id' => $id,
            'body' => $data,
        ];

        try {
            $response = $this->client->index($params);
            $res = [
                'code' => 200,
                'message' => "success",
                'data' => $response
            ];
        } catch (Missing404Exception $exception) {
            $res = [
                'code' => $exception->getCode(),
                'message' => json_decode($exception->getMessage(), true),
                'data' => [],
            ];
        }
        return $res;
    }

    /**
     * 删除doc
     * @param string $indexName 索引名
     * @param int $id 文档id
     * @return array
     */
    public function deleteDoc($indexName = "", int $id)
    {
        $data = [
            'index' => $indexName,
            'id' => $id,
        ];
        try {
            $response = $this->client->delete($data);
            $res = [
                'code' => 200,
                'message' => "success",
                'data' => $response
            ];
        } catch (Missing404Exception $exception) {
            $res = [
                'code' => $exception->getCode(),
                'message' => json_decode($exception->getMessage(), true),
                'data' => [],
            ];
        }
        return $res;
    }

    /**
     * 修改doc
     * @param string $indexName
     * @param int $id
     * @param array $data
     * @return array
     */
    public function updateDoc($indexName = "", int $id, $data = [])
    {
        //修改指定索引指定文档的内容
        $params = [
            //索引
            'index' => $indexName,
            //类型 es6之后一个索引对应一个type
            'type' => '_doc',
            //文档id
            'id' => $id,
            //字段值
            'body' => [
                'doc' => [
                    $data
                ]
            ],
        ];
        try {
            $response = $this->client->update($params);
            $res = [
                'code' => 200,
                'message' => "success",
                'data' => $response
            ];
        } catch (Missing404Exception $exception) {
            $res = [
                'code' => $exception->getCode(),
                'message' => json_decode($exception->getMessage(), true),
                'data' => [],
            ];
        }
        return $res;
    }

    /**
     * @param string $indexName
     * @param array $body
     * @return array
     */
    public function searchDoc($indexName = "", $body =[])
    {
        $params = [
            'index' => $indexName,
            'body' => $body,
        ];
        try {
            $response = $this->client->search($params);
            $res = [
                'code' => 200,
                'message' => "success",
                'data' => $response
            ];
        } catch (Missing404Exception $exception) {
            $res = [
                'code' => $exception->getCode(),
                'message' => json_decode($exception->getMessage(), true),
                'data' => [],
            ];
        }
        return $res;
    }
}
创建索引
//控制器Api下面的代码
public function createIndex()
    {
       //获取上面的es功能类
        $es = getEs();
        $data = [
            //文档的字段以及字段的类型
            'uses_id' => [
                'type' => 'integer'
            ],
            'nickname' => [
                //keyword类型的字段只能通过精确值搜索到
                'type'=> 'keyword'
            ],
            'pageViews' => [
                'type' => 'integer'
            ],
            'likes' => [
                'type' => 'integer'
            ],
            'title' => [
                'type' => 'text',
                //ik分词器的ik_max_word模式
                'analyzer' => 'ik_max_word',
                'search_analyzer' => 'ik_max_word'
            ],
            'content' => [
                'type' => 'text',
                //ik分词器的ik_max_word模式
                'analyzer' => 'ik_max_word',
                'search_analyzer' => 'ik_max_word'
            ],
            'create_time' => [
                'type' => 'integer'
            ],
            'update_time' => [
                'type' => 'date',
                //date的格式
                "format" => "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
            ],
        ];
    	//创建索引
       $res = $es->createIndex('articles',5,1,$data);
        if ($res) {
            success($res);
        }
        fail($res);
    }

结果

在这里插入图片描述

将全部的文章放入es中

这里面的字段都是检索之后需要展示的字段,其他不需要展示的字段为放入es中

//控制器 Job/job下的代码
public function articleToes()
    {
        $article = $this->article_model->findAll();
        $es = getEs();
        foreach ($article as $v) {
            $data = [
                'user_id' => $v['user_id'],
                'nickname' => $v['nickname'],
                'desc' => $v['desc'],
                'content' => $v['content'],
                'title' => $v['title'],
                'pageViews' => $v['pageViews'],
                'likes' => $v['likes'],
                'create_time' => $v['create_time'],
                'update_time' => date('Y-m-d H:i:s', $v['update_time'])
            ];
            $es->SaveDoc('articles', $v['id'], $data);
        }
    }

结果

在这里插入图片描述

对文章进行检索
//Article控制器代码
public function search()
    {
        $data = $this->input->post();
        if (!empty($data['keyword'])){
            $body = [
                'query' => [
                    'bool' => [
                        //这里的should相当于or操作,还有must相当于and操作
                        'should' => [
                            ['match' => ['title' => $data['keyword'] ] ],
                            ['match' => ['desc' => $data['keyword'] ] ],
                            ['match' => ['content' => $data['keyword'] ] ],
                            ['match' => ['nickname' => $data['keyword'] ] ],
                        ]
                    ]
                ]
            ];
            $res = $this->es->searchDoc('articles', $body);
            success($res);
        }
    }

结果:

在这里插入图片描述
这里对es类进行了简单的封装,以及简单的操作,后续还会对代码进行优化.

新增功能

新增封装了批量插入功能函数

 /**
     * 批量插入数据
     * @param string $indexName
     * @param $data  带上id
     * @param bool $isId 是否在内容中也保存id,默认不保存
     * @return array
     */
    public function CreateDocs($indexName = "", $data, $isId = false)
    {
        $params = ["body" => []];
        foreach ($data as $k => $v) {
            if (empty($v['id'])) {
                //数组中不存在id
                $params['body'][] = [
                    'index' => [
                        '_index' => $indexName,
                    ]
                ];
            } else {
                //数组中存在id
                $params['body'][] = [
                    'index' => [
                        '_index' => $indexName,
                        //设置id
                        '_id' => $v['id']
                    ]
                ];
                //内容中不展示id字段
                if (!$isId) {
                    unset($v['id']);
                }
            }
            //内容
            $params['body'][] = $v;
        }
        try {
            $response = $this->client->bulk($params);
            $res = [
                'code' => 200,
                'message' => "success",
                'data' => $response
            ];
        } catch (Missing404Exception $exception) {
            $res = [
                'code' => $exception->getCode(),
                'message' => json_decode($exception->getMessage(), true),
                'data' => [],
            ];
        }
        return $res;
    }

对查询出来的数据格式和分页做优化(放在公共助手函数中)

//测试查询 这里只测试页码分页效果
function findEs()
    {
        $data = $this->input->get();
        $page = $data['page'] ? $data['page'] : 1; //当前页数
        $pageSize = 2; //页码
        $from = ($page - 1) * $pageSize;
        $es = getEs();
        $body = [
            'query' => [
                'bool' => [
                    "should" => [
                        ["match" => ['title' => "Python"]],
                        ["match" => ['desc' => "Python"]],
                        ["match" => ['nickname' => "Python"]],
                    ]
                ]
            ],
            "from" => $from,
            "size" => $pageSize,
        ];
        $res = $es->searchDoc('articles', $body);
        $result = esFormat($res,$page,$pageSize);
        responseArray($result);
    }




/*
 * 格式化查询到的es结果
 */
if (!function_exists("esFormat")) {
    function esFormat($data,$page = 0,$pageSize)
    {
        if (empty($data['data']) || $data['code'] != 200) {
            return returnArr(400, '', '查找失败');
        }
        if (empty($data['data']['hits']['total'])) {
            return returnArr(400, '', '暂无数据');
        }
        $formatData = array_column($data['data']['hits']['hits'], "_source");
        $total = $data["data"]['hits']['total']['value'];
        $res = [
            "list" => $formatData,
        ];
        if ($page){
            $res["paginate"] = [
                'page' => $page, //页码
                "pageSize" => $pageSize, //一页展示个数
                "total" => $total //总数
            ];
        }

        return returnArr(200, $res, "查询成功");
    }
}

分页展示没有问题
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值