php elasticsearch 教程
原文链接:https://www.tizi365.com/archives/951.html
PDF https://www.jone.xyz/datafile/php elasticsearch 教程.pdf
一、php elasticsearch 教程
php elasticsearch教程,主要从php角度讲解elasticsearch的增删改查等操作。
提示:如果不熟悉Elasticsearch的相关概念和查询语法,请参考:Elasticsearch 教程,这里不再重复介绍ES的核心概念和查询语法。
php elasticsearch 教程,主要围绕ES官方php客户端进行讲解。
版本说明
注意自己的Php版本和Elasticsearch版本的对应关系,选择合适的php elasticsearch客户端版本。
Elasticsearch版本 | php ES客户端版本 | php版本 |
>= 7.0, < 8.0 | >= 7.0 | > 7.1 |
>= 6.6, ⇐ 6.7 | 6.7.x | > 7.0 |
>= 6.0, ⇐ 6.5 | 6.5.x | > 7.0 |
>= 5.0, < 6.0 | 5.5.0 | > 5.6, < 7.0 |
最新的php es客户端版本是:7.8.0, 需要Php7.1以上,如果需要支持es 5版本,选择es客户端版本5.5.0即可,php5.6就可以使用。
安装依赖
使用Composer方式安装
依赖配置
{
"require": {
"elasticsearch/elasticsearch": "~7.0"
}
}
安装
切换到项目目录,执行命令。
php composer install
提示:关于composer命令路径,安装composer后,将composer命令路径添加到PATH环境变量即可。
加载依赖
在php入口文件,加载autoload脚本,就可以自动加载composer安装的第三方包。
require 'vendor/autoload.php';
创建client
在使用ES之前,需要先创建一个ES client对象,用于配置Elasticsearch连接地址,账号、密码、发送ES请求等等。
use Elasticsearch\ClientBuilder;
// ES服务端配置,这里配置两个ES服务地址,这里是免密码访问的配置方式。
$hosts = [
'localhost:9200',
'localhost:9201',
];
$client = ClientBuilder::create() // 实例化一个ClientBuilder对象,通过他配置client
->setHosts($hosts) // 设置ES服务端配置
->build(); // 创建Client
插入文档
$params = [
'index' => 'my_index', // 索引名
'id' => 'my_id', // 文档id
'body' => ['testField' => 'abc'] // 文档内容,最终会转成json,因此支持任意结构
];
// 通过client::index方法,插入文档,如果
$response = $client->index($params);
print_r($response);
输出结果
Array
(
[_index] => my_index // 索引名
[_type] => _doc // 新版ES已经没什么作用了
[_id] => my_id // 文档id
[_version] => 1 // 文档版本号
[created] => 1
)
提示:es 的index操作,除了插入文档,其实也可以更新文档,如果文档id,已经存在就会更新文档,不过这里的更新操作是全量更新,就是新更新的文档内容会覆盖掉老的文档,而不是局部更新,例如:老的文档内容包含order_id,title两个字段,通过index更新title字段内容,那么新的文档内容只有title字段,order_id字段被丢去了,如果非要使用index实现更新操作,则需要把所有老的字段都写一遍。
读取文档
根据文档id查询内容
$params = [
'index' => 'my_index',// 索引名
'id' => 'my_id' // 需要查询的文档id
];
// 执行请求
$response = $client->get($params);
print_r($response);
输出结果
Array
(
[_index] => my_index // 索引名
[_type] => _doc
[_id] => my_id // 文档id
[_version] => 1
[found] => 1
[_source] => Array // 文档内容
(
[testField] => abc
)
)
搜索文档
$params = [
'index' => 'my_index', // 索引名
'body' => [ // ES查询语法
'query' => [
'match' => [
'testField' => 'abc'
]
]
]
];
// 执行ES请求
$response = $client->search($params);
print_r($response);
输出结果
Array
(
[took] => 1 // 执行时间
[timed_out] => // 是否超时
[_shards] => Array
(
[total] => 5
[successful] => 5
[failed] => 0
)
[hits] => Array // 搜索结果
(
[total] => 1 // 匹配文档数量
[max_score] => 0.30685282 // 匹配分值
[hits] => Array // 匹配文档内容数组,下面就是匹配的一个个文档内容
(
[0] => Array
(
[_index] => my_index
[_type] => _doc
[_id] => my_id
[_score] => 0.30685282
[_source] => Array
(
[testField] => abc
)
)
)
)
)
删除文档
$params = [
'index' => 'my_index', // 索引名
'id' => 'my_id' // 文档id
];
// 执行删除请求
$response = $client->delete($params);
print_r($response);
输出结果
Array
(
[found] => 1 // 是否匹配文档
[_index] => my_index // 索引名
[_type] => _doc
[_id] => my_id // 删除的文档id
[_version] => 2
)
删除索引
$deleteParams = [
'index' => 'my_index' // 索引名
];
$response = $client->indices()->delete($deleteParams);
print_r($response);
输出
Array
(
[acknowledged] => 1 // es服务端接受处理
)
其他详细介绍,请参考后续章节。
二、php elasticsearch连接配置
php的elasticsearch连接配置主要通过ClientBuilder工具类完成。
常用的配置项如下:
- elasticsearch连接地址
- elasticsearch认证账号和密码
- 请求重试次数
格式1
// 直接配置多个ES服务地址,支持多种类型的地址
$hosts = [
'192.168.1.1:9200', // IP + Port
'192.168.1.2', // 仅 IP
'mydomain.server.com:9201', // 域名 + Port
'mydomain2.server.com', // 仅 域名
'https://localhost', // https协议格式
'https://192.168.1.3:9200', // https协议格式
// 支持设置es连接的账号和密码
'https://username:password@foo.com:9200/elastic'
];
$client = ClientBuilder::create() // 创建 ClientBuilder
->setHosts($hosts) // 设置 hosts
->build(); // 构建client对象
ES连接地址详解:
schema://username:password@host:port/path
参数说明:
- schema – http协议类型,支持http和https
- username – 账号
- password – 密码
- host – 域名或者ip地址
- port – 端口号
- path – url路径
ES连接地址例子
https://admin:123456@foo.com:9200/elastic
格式2
支持详细的配置Elasticsearch信息,支持配置账号和密码
// 每一个ES服务地址,是一个数组,支持配置详细的连接信息
hosts = [
// 等价连接地址: "https://username:password!#$?*abc@foo.com:9200/elastic"
[
'host' => 'foo.com', // 域名
'port' => '9200', // 端口
'scheme' => 'https', // 协议
'path' => '/elastic', // path
'user' => 'username', // 账号
'pass' => 'password!#$?*abc' // 密码
],
// 等价连接地址 "http://localhost:9200/"
[
'host' => 'localhost', // 仅配置域名
]
];
$client = ClientBuilder::create() // 创建 ClientBuilder对象
->setHosts($hosts) // 设置 hosts
->build(); // 构建client对象
请求重试次数
$client = ClientBuilder::create()
->setRetries(2) // 设置连接请求次数为2
->build();
三、php elasticsearch 文档操作(CRUD)
Elasticsearch文档的基础操作主要包括:创建、查询、更新、删除、批量查询、批量更新、批量删除。
下面介绍php对elasticsearch文档的基础操作
创建文档
$params = [
'index' => 'my_index', // 索引名
'id' => 'my_id', // 设置文档Id, 可以忽略Id, Es也会自动生成
'body' => [ 'testField' => 'abc'] // 设置文档内容
];
// 创建文档
$response = $client->index($params);
bulk批量创建文档
通过bulk实现批量插入文档,bulk操作,都是一行操作说明,一行操作相关数据的方式进行组织内容。
// 循环插入100条数据
for($i = 0; $i < 100; $i++) {
// bulk操作,先拼接一行index操作参数
$params['body'][] = [
'index' => [
'_index' => 'my_index', // 索引名
'id' => 'my_id', // 设置文档Id, 可以忽略Id, Es也会自动生成
]
];
// 接着拼接index操作的内容,这里就是我们需要插入的文档内容
$params['body'][] = [
'my_field' => 'my_value',
'second_field' => 'some more values'
];
}
// 执行bulk操作
$responses = $client->bulk($params);
查询文档
根据文档id查询
$params = [
'index' => 'my_index', // 索引名
'id' => 'my_id' // 需要查询的文档id
];
// 执行请求
$response = $client->get($params);
局部更新文档
$params = [
'index' => 'my_index', // 索引名
'id' => 'my_id', // 文档id
'body' => [ // ES请求体内容
'doc' => [ // doc包含的内容就是我们想更新的字段内容
'new_field' => 'abc'
]
]
];
// 执行ES请求
$response = $client->update($params);
update by query
根据查询条件匹配更新内容
$params = [
'index' => 'my_index', // 索引名
// 如果出现版本冲突,如何处理?proceed表示继续更新,abort表示停止更新
'conflicts' => 'proceed',
'body' => [ // ES请求体内容
// 通过script更新文档内容,ctx._source代表匹配到的文档
// 含义等于 counter字段值 + 1
'script' => 'ctx._source.counter++',
'query' => [ // 设置查询条件,跟es查询语法一致
"term" => [
'user_id' => 'kimchy'
]
],
],
];
$response = $client->updateByQuery($params);
提示:ES查询语法,请参考:Elasticsearch查询语法,只要将ES查询语法转换成PHP数组即可
Upserts
更新文档内容,如果文档不存在则插入文档。
$params = [
'index' => 'my_index', // 索引名
'id' => 'my_id', // 文档id
'body' => [ // es请求体
'script' => [ // 通过脚本更新内容
// 设置脚本内容,ctx._source代表匹配的文档内容,脚本含义: counter字段值 + 脚本参数count
'source' => 'ctx._source.counter += params.count',
'params' => [ // 设置脚本参数
'count' => 4
],
],
// 如果文档不存在,则插入upsert设置的内容
// upsert的内容就相当于默认值
'upsert' => [
'counter' => 1
],
]
];
// 执行请求
$response = $client->update($params);
删除文档
根据文档Id删除文档
$params = [
'index' => 'my_index', // 索引名
'id' => 'my_id' // 文档id
];
// 执行请求
$response = $client->delete($params);
delete by query
根据查询条件,批量删除文档
$params = [
'index' => 'my_index', // 索引名
// 如果出现版本冲突,如何处理?proceed表示继续更新,abort表示停止更新
'conflicts' => 'proceed',
'body' => [ // ES请求体内容
'query' => [ // 设置查询条件,跟es查询语法一致
"term" => [
'user_id' => 'kimchy'
]
],
],
];
$client->deleteByQuery($params);
四、php elasticsearch 索引管理
php elasticsearch 索引管理常用操作主要包括:创建索引、删除索引、查询索引结构,修改索引设置。
创建索引
虽然,ES可以自动创建索引,不过实际项目中,通常需要预先创建索引结构,明确指定数据类型,避免出现ES自动创建的字段类型不是你想要的类型。
$client = ClientBuilder::create()->build();
$params = [
'index' => 'my_index', // 索引名
'body' => [ // es 索引结构定义
'settings' => [ // 索引配置
'number_of_shards' => 3, // 分片数量
'number_of_replicas' => 2 // 副本数量
],
'mappings' => [ // mapping定义,即索引结构定义
'_source' => [
'enabled' => true
],
'properties' => [
'first_name' => [
'type' => 'keyword'
],
'age' => [
'type' => 'integer'
]
]
]
]
];
// 创建索引
$response = $client->indices()->create($params);
ES中mappings负责索引字段和数据类型,具体的ES mapping语法,请参考:Elasticsearch mapping,将ES的mapings定义的json结构转成php数组即可,
删除索引
$params = [
'index' => 'my_index' // 索引名
];
$response = $client->indices()->delete($params);
查询索引结构
查询首页的mapping定义
// 查询所有的mapping定义
$response = $client->indices()->getMapping();
// 查询指定索引的Mapping定义
$params = [
'index' => 'my_index' // 索引名
];
$response = $client->indices()->getMapping($params);
// 查询my_index和my_index2两个索引的mapping定义
$params = [
'index' => [ 'my_index', 'my_index2' ]
];
$response = $client->indices()->getMapping($params);
修改索引设置
$params = [
'index' => 'my_index', // 索引名
'body' => [
'settings' => [ // 修改设置
'number_of_replicas' => 5, // 副本数
]
]
];
$response = $client->indices()->putSettings($params);
五、php elasticsearch 搜索详解
本章主要讲解php Elasticsearch的搜索的写法,大体上php Elasticsearch的写法还是跟elasticsearch查询语法保持一致,区别就是elasticsearch使用的是json结构,需要转换成php数组。
如果不熟悉elasticsearch查询语法和相关概念,可以先看看elasticsearch查询语法教程,这里不再重复。
下面通过一些例子对比下,elasticsearch查询语法和php的写法之间的区别
php es查询语法差异
es查询语法
curl -XGET 'localhost:9200/my_index/_search' -d '{
"query" : {
"match" : {
"testField" : "abc"
}
}
}'
转换成php后的写法
$params = [
'index' => 'my_index', // 索引名
//body保存es 请求体内容, 这里的内容跟es查询语法保持一致,区别就是需要转成php数组格式
'body' => [
// 这里的内容跟上面查询语法一致
'query' => [
'match' => [
'testField' => 'abc'
]
]
]
];
// 通过search执行查询请求。
$results = $client->search($params);
提示:php elasticsearch的查询语法跟elasticsearch查询语法完全一致,只要将json格式转换成php数组即可, 详情参考:elasticsearch查询语法。
处理搜索结果
$params = [
'index' => 'my_index',
'body' => [
'query' => [
'match' => [
'testField' => 'abc'
]
]
]
];
$results = $client->search($params);
// 下面处理查询结果
$milliseconds = $results['took']; // 获取请求执行时间,单位毫秒
// 获取匹配的最大分值
$maxScore = $results['hits']['max_score'];
// 获取匹配的文档结果,是一个文档列表,建议打印出来看看
$list = $results['hits']['hits'];
复杂的查询例子
es查询例子
curl -XGET 'localhost:9200/my_index/_search' -d '{
"query" : {
"bool" : {
"filter" : {
"term" : { "my_field" : "abc" }
},
"should" : {
"match" : { "my_other_field" : "xyz" }
}
}
}
}'
转换成php代码
$params = [
'index' => 'my_index', // 索引名
'body' => [ // es 请求体,下面的内容,仔细跟上面对比下,完全一致
'query' => [
'bool' => [
'filter' => [
'term' => [ 'my_field' => 'abc' ]
],
'should' => [
'match' => [ 'my_other_field' => 'xyz' ]
]
]
]
]
];
$results = $client->search($params);
分页
$params = [
'index' => 'my_index', // 索引名
'from' => 0, // 分页参数, 开始偏移配置
'size' => 100, // 分页参数 - 分页大小,默认 10
'body' => [// es查询条件
'query' => [
'match' => [
'testField' => 'abc'
]
]
]
];
// 通过search执行查询请求。
$results = $client->search($params);
排序
$params = [
'index' => 'my_index', // 索引名
'from' => 0, // 分页参数, 开始偏移配置
'size' => 100, // 分页参数 - 分页大小,默认 10
'sort' => [ // 设置排序条件, 支持多个排序字段
'shop_id' => [ // 排序字段
'order' => 'desc' // 排序方向: asc升序,desc降序
]
],
'body' => [// es查询条件
'query' => [
'match' => [
'testField' => 'abc'
]
]
]
];
// 通过search执行查询请求。
$results = $client->search($params);
六、php elasticsearch 聚合查询(Aggregation)
Elasticsearch中的聚合查询,类似SQL的SUM/AVG/COUNT/GROUP BY分组查询,主要用于统计分析场景。
这里主要介绍PHP Elasticsearch 聚合查询的写法,如果不了解ES聚合查询,请参考 ES聚合查询基本概念和语法。
提示:ES聚合查询语法使用的是json格式描述,在php中使用需要转换成php数组描述
例子
下面是ES通过rest api执行聚合查询的例子,aggs字段描述的就是聚合查询语句。
GET /order/_search
{
"size" : 0, // 设置size=0的意思就是,仅返回聚合查询结果,不返回普通query查询结果。
"aggs" : { // 聚合查询语句的简写
"popular_colors" : { // 给聚合查询取个名字,叫popular_colors
"terms" : { // 聚合类型为,terms,terms是桶聚合的一种,类似SQL的group by的作用,根据字段分组,相同字段值的文档分为一组。
"field" : "color" // terms聚合类型的参数,这里需要设置分组的字段为color,根据color分组
}
}
}
}
翻译成PHP代码则写法如下
$params = [
'index' => 'order', // 索引名
'size' => 0, // 设置0,表示不返回匹配结果,仅返回聚合查询统计结果
'body' => [// es请求体内容
'aggs' => [ // 聚合查询语句,这里的语法结构跟ES聚合查询语句一致
'popular_colors' => [
'terms' => [
'field' => 'color'
]
]
]
]
];
// 通过search执行查询请求。
$results = $client->search($params);
// 聚合分析结构通常保存在$results['aggregations'] 字段中,可以打印$results观察下,输出的内容,基本上跟ES restful api查询的结果类似。
php的aggs聚合查询语句跟ES聚合查询语法一致,区别就是一个是json格式一个是php数组格式。