官方地址:
https://www.elastic.co/guide/cn/elasticsearch/php/current/index.html
# 1. 安装
{
"require": {
"elasticsearch/elasticsearch": "~7.0"
}
}
2
3
4
5
require 'vendor/autoload.php';
$client = Elasticsearch\ClientBuilder::create()->build();
2
3
# 2. 连接
# 2.1 弹性云
您可以使用 连接到 Elastic Cloud 基本身份验证 :
$client = ClientBuilder :: create ()
-> setElasticCloudId ( 'cloud-id' )
-> setBasicAuthentication ( 'username' , 'password' )
-> build ();
2
3
4
其中 cloud-id
在部署 UI 中报告,username
, password
部署新的云实例时生成。 您需要存储 username
和 password
因为它们将无法通过 UI 使用。
或者使用 API 密钥 :
$client = ClientBuilder :: create ()
-> setElasticCloudId ( 'cloud-id' )
-> setApiKey ( 'id' , 'key' )
-> build ();
2
3
4
其中 id
和 key
在您创建新的 API 密钥时生成。 API 密钥是 相当于 Base64(id
:key
)。 您需要存储 API 密钥,因为它会 无法通过 UI 使用。
# 2.2 HTTP 认证
如果您的 Elasticsearch 服务器受 HTTP 身份验证保护,您需要提供 ES-PHP 的凭据,以便请求可以在服务器端进行身份验证。 身份验证凭据作为主机阵列的一部分提供 实例化客户端:
$hosts = [
'http://user:pass@localhost:9200' , // HTTP 基本认证
'http://user2:pass2@other-host.com:9200' // 不同主机上的不同凭证
];
$client = ClientBuilder :: create ()
-> setHosts ( $hosts )
-> build ();
2
3
4
5
6
7
8
每个主机都提供凭据,这允许每个主机拥有自己的设置 的凭据。 发送到集群的所有请求都使用适当的凭据 取决于正在与之交谈的节点。
# 2.3 ApiKey 认证
如果您的 Elasticsearch 集群由 API 密钥保护,如所述 在这里 (opens new window),您可以使用这些值 将客户端与您的集群连接,如下面的代码所示 片段。
$client = ClientBuilder :: create ()
-> setApiKey ( 'id' , 'api_key' )
-> build ();
2
3
ApiKey 对 id
和 api_key
来自创建 API 密钥响应。
# 3. 快速使用
# 3.1 创建索引
现在您开始新鲜(没有数据或索引),添加一个自定义的新索引 设置:
$params = [
'index' => 'my_index',
'body' => [
'settings' => [
'number_of_shards' => 2,
'number_of_replicas' => 0
]
]
];
$response = $client->indices()->create($params);
print_r($response);
2
3
4
5
6
7
8
9
10
11
12
Elasticsearch 现在使用您选择的设置创建该索引并返回一个 确认:
Array
(
[acknowledged] => 1
)
2
3
4
# 3.2 删除索引
由于 Elasticsearch 的动态特性,您自动添加的第一个文档 使用一些默认设置构建了一个索引。 删除该索引并指定您的 稍后自己设置:
$deleteParams = [
'index' => 'my_index'
];
$response = $client->indices()->delete($deleteParams);
print_r($response);
2
3
4
5
响应:
Array
(
[acknowledged] => 1
)
2
3
4
# 3.3 索引文档
在 elasticsearch-php 中,几乎所有的东西都是由关联数组配置的。 这 REST 端点、文档和可选参数 - 一切都是关联的 大批。
要索引一个文档,我们需要指定三个信息:index、id 和文档正文。 这是通过构造一个关联数组来完成的 键:值对。 请求正文本身就是一个带有 key:value 的关联数组 与文档中的数据对应的对:
$params = [
'index' => 'my_index' ,
'id' => 'my_id' ,
'body' => [ 'testField' => 'abc' ]
];
$response = $client -> index ( $params );
print_r ( $response );
2
3
4
5
6
7
8
您收到的响应表明该文档是在 您指定的索引。 响应是一个关联数组,其中包含一个 Elasticsearch 返回的 JSON 的解码版本:
Array
(
[_index] => my_index
[_type] => _doc
[_id] => my_id
[_version] => 1
[created] => 1
)
2
3
4
5
6
7
8
# 3.4 获取文档
让我们获取我们刚刚索引的文档。 这将返回文档:
$params = [
'index' => 'my_index' ,
'id' => 'my_id'
];
$response = $client -> get ( $params );
print_r ( $response );
2
3
4
5
6
7
响应包含元数据,例如索引、版本等以及 _source
字段,这是您发送到 Elasticsearch 的原始文档。
数组
(
[ _index ] => my_index
[ _type ] => _doc
[ _id ] => my_id
[ _version ] => 1
[ found ] => 1
[ _source ] => Array
(
[ testField ] => abc
)
)
2
3
4
5
6
7
8
9
10
11
12
13
# 3.5 搜索文档
搜索是 Elasticsearch 的标志,所以让我们执行搜索。 我们将使用 这 match
查询作为演示:
$params = [
'index' => 'my_index',
'body' => [
'query' => [
'match' => [
'testField' => 'abc'
]
]
]
];
$response = $client->search($params);
print_r($response);
2
3
4
5
6
7
8
9
10
11
12
13
这里的反应与之前的不同。 你可以看到元数据 ( took
, timed_out
等)和一个名为的数组 hits
. 这代表你 搜索结果。 代替 hits
是另一个名为的数组 hits
, 其中包含 个人搜索结果:
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
)
)
)
)
)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 3.6 删除文档
好的,让我们继续删除我们之前添加的文档:
$params = [
'index' => 'my_index' ,
'id' => 'my_id'
];
$response = $client -> delete ( $params );
print_r ( $response );
2
3
4
5
6
7
此语法与 get
句法。 唯一的区别是 : delete
代替 get
. 响应确认文件是 删除:
Array
(
[found] => 1
[_index] => my_index
[_type] => _doc
[_id] => my_id
[_version] => 2
)
2
3
4
5
6
7
8
# 4. 配置
客户端的几乎每个方面都是可配置的。 大多数用户只需要 配置一些参数以满足他们的需要,但完全可以 如果需要,更换大部分内部部件。
自定义配置是在客户端实例化之前完成的,通过 ClientBuilder 助手对象。 您可以找到所有配置选项和 检查可帮助您更换各种组件的示例代码。
要了解有关 PHP 中 JSON 的更多信息,请阅读 PHP 中的 处理 JSON 数组和对象 (opens new window)。
- 主机配置 (opens new window)
- 设置重试 (opens new window)
- HTTP 元数据 (opens new window)
- 启用记录器 (opens new window)
- 配置 HTTP 处理程序 (opens new window)
- 命名空间 (opens new window)
- 连接池 (opens new window)
- 选择器 (opens new window)
- 序列化器 (opens new window)
- 设置自定义 ConnectionFactory (opens new window)
- 设置端点闭包 (opens new window)
- 从配置哈希构建客户端 (opens new window)
- 每个请求配置 (opens new window)
- 未来模式 (opens new window)
# 5. 操作
此页面包含执行各种 Elasticsearch 操作所需的信息 通过使用客户端。
- 索引管理操作 (opens new window)
- 搜索操作 (opens new window)
- 索引文件 (opens new window)
- 获取文件 (opens new window)
- 更新文件 (opens new window)
- 删除文件 (opens new window)
# 5.1 索引管理操作
# 5.1.1 创建索引
$client = ClientBuilder::create()->build();
$params = [
'index' => 'my_index'
];
// Create the index
$response = $client->indices()->create($params);
2
3
4
5
6
7
带参数:
$client = ClientBuilder::create()->build();
$params = [
'index' => 'my_index',
'body' => [
'settings' => [
'number_of_shards' => 3,
'number_of_replicas' => 2
],
'mappings' => [
'_source' => [
'enabled' => true
],
'properties' => [
'first_name' => [
'type' => 'keyword'
],
'age' => [
'type' => 'integer'
]
]
]
]
];
// Create the index with mappings and settings now
$response = $client->indices()->create($params);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
高级用法:
$params = [
'index' => 'reuters',
'body' => [
'settings' => [
'number_of_shards' => 1,
'number_of_replicas' => 0,
'analysis' => [
'filter' => [
'shingle' => [
'type' => 'shingle'
]
],
'char_filter' => [
'pre_negs' => [
'type' => 'pattern_replace',
'pattern' => '(\\w+)\\s+((?i:never|no|nothing|nowhere|noone|none|not|havent|hasnt|hadnt|cant|couldnt|shouldnt|wont|wouldnt|dont|doesnt|didnt|isnt|arent|aint))\\b',
'replacement' => '~$1 $2'
],
'post_negs' => [
'type' => 'pattern_replace',
'pattern' => '\\b((?i:never|no|nothing|nowhere|noone|none|not|havent|hasnt|hadnt|cant|couldnt|shouldnt|wont|wouldnt|dont|doesnt|didnt|isnt|arent|aint))\\s+(\\w+)',
'replacement' => '$1 ~$2'
]
],
'analyzer' => [
'reuters' => [
'type' => 'custom',
'tokenizer' => 'standard',
'filter' => ['lowercase', 'stop', 'kstem']
]
]
]
],
'mappings' => [
'properties' => [
'title' => [
'type' => 'text',
'analyzer' => 'reuters',
'copy_to' => 'combined'
],
'body' => [
'type' => 'text',
'analyzer' => 'reuters',
'copy_to' => 'combined'
],
'combined' => [
'type' => 'text',
'analyzer' => 'reuters'
],
'topics' => [
'type' => 'keyword'
],
'places' => [
'type' => 'keyword'
]
]
]
]
];
$client->indices()->create($params);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# 5.1.2 删除索引
$params = ['index' => 'my_index'];
$response = $client->indices()->delete($params);
2
# 5.1.3 索引配置
$params = [
'index' => 'my_index',
'body' => [
'settings' => [
'number_of_replicas' => 0,
'refresh_interval' => -1
]
]
];
$response = $client->indices()->putSettings($params);
2
3
4
5
6
7
8
9
10
11
# 5.1.4 获取索引配置
// Get settings for one index
$params = ['index' => 'my_index'];
$response = $client->indices()->getSettings($params);
// Get settings for several indices
$params = [
'index' => [ 'my_index', 'my_index2' ]
];
$response = $client->indices()->getSettings($params);
2
3
4
5
6
7
8
9
# 5.1.5 配置索引映射
// Set the index and type
$params = [
'index' => 'my_index',
'body' => [
'_source' => [
'enabled' => true
],
'properties' => [
'first_name' => [
'type' => 'text',
'analyzer' => 'standard'
],
'age' => [
'type' => 'integer'
]
]
]
];
// Update the index mapping
$client->indices()->putMapping($params);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 5.1.6 获取索引映射配置
// Get mappings for all indices
$response = $client->indices()->getMapping();
// Get mappings in 'my_index'
$params = ['index' => 'my_index'];
$response = $client->indices()->getMapping($params);
// Get mappings for two indices
$params = [
'index' => [ 'my_index', 'my_index2' ]
];
$response = $client->indices()->getMapping($params);
2
3
4
5
6
7
8
9
10
11
12
# 5.2 搜索操作
# 5.2.1 匹配查询
curl -XGET 'localhost:9200/my_index/_search' -d '{
"query" : {
"match" : {
"testField" : "abc"
}
}
}'
2
3
4
5
6
7
$params = [
'index' => 'my_index',
'body' => [
'query' => [
'match' => [
'testField' => 'abc'
]
]
]
];
$results = $client->search($params);
$milliseconds = $results['took'];
$maxScore = $results['hits']['max_score'];
$score = $results['hits']['hits'][0]['_score'];
$doc = $results['hits']['hits'][0]['_source'];
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 5.2.2 bool查询
curl -XGET 'localhost:9200/my_index/_search' -d '{
"query" : {
"bool" : {
"must": [
{
"match" : { "testField" : "abc" }
},
{
"match" : { "testField2" : "xyz" }
}
]
}
}
}'
2
3
4
5
6
7
8
9
10
11
12
13
14
$params = [
'index' => 'my_index',
'body' => [
'query' => [
'bool' => [
'must' => [
[ 'match' => [ 'testField' => 'abc' ] ],
[ 'match' => [ 'testField2' => 'xyz' ] ],
]
]
]
]
];
$results = $client->search($params);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 5.2.3 复杂查询
curl -XGET 'localhost:9200/my_index/_search' -d '{
"query" : {
"bool" : {
"filter" : {
"term" : { "my_field" : "abc" }
},
"should" : {
"match" : { "my_other_field" : "xyz" }
}
}
}
}'
2
3
4
5
6
7
8
9
10
11
12
$params = [
'index' => 'my_index',
'body' => [
'query' => [
'bool' => [
'filter' => [
'term' => [ 'my_field' => 'abc' ]
],
'should' => [
'match' => [ 'my_other_field' => 'xyz' ]
]
]
]
]
];
$results = $client->search($params);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 5.2.4 分页查询
$client = ClientBuilder::create()->build();
$params = [
"scroll" => "30s", // how long between scroll requests. should be small!
"size" => 50, // how many results *per shard* you want back
"index" => "my_index",
"body" => [
"query" => [
"match_all" => new \stdClass()
]
]
];
// Execute the search
// The response will contain the first batch of documents
// and a scroll_id
$response = $client->search($params);
// Now we loop until the scroll "cursors" are exhausted
while (isset($response['hits']['hits']) && count($response['hits']['hits']) > 0) {
// **
// Do your work here, on the $response['hits']['hits'] array
// **
// When done, get the new scroll_id
// You must always refresh your _scroll_id! It can change sometimes
$scroll_id = $response['_scroll_id'];
// Execute a Scroll request and repeat
$response = $client->scroll([
"scroll_id" => $scroll_id, //...using our previously obtained _scroll_id
"scroll" => "30s" // and the same timeout window
]
);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 5.3 索引文档
# 5.3.1 单个索引文档
提供 ID 值。
$params = [
'index' => 'my_index',
'id' => 'my_id',
'body' => [ 'testField' => 'abc']
];
// 文档将被索引到 my_index/_doc/my_id
$response = $client->index($params);
2
3
4
5
6
7
8
省略 ID 值。
$params = [
'index' => 'my_index',
'body' => [ 'testField' => 'abc']
];
// 文档将被索引到 my_index/_doc/<autogenerated ID>
$response = $client->index($params);
2
3
4
5
6
7
如果需要设置其他参数,例如 routing
值,您指定 数组中的那些 index
, 和别的。 例如,让我们设置 这个新文档的路由和时间戳:
附加参数。
$params = [
'index' => 'my_index' ,
'id' => 'my_id' ,
'routing' => 'company_xyz' ,
'timestamp' => strtotime ( "-1d" ),
'body' => [ 'testField' => 'abc' ]
];
$response = $client -> index ( $params );
2
3
4
5
6
7
8
# 5.3.2 批量索引文档
for($i = 0; $i < 100; $i++) {
$params['body'][] = [
'index' => [
'_index' => 'my_index',
]
];
$params['body'][] = [
'my_field' => 'my_value',
'second_field' => 'some more values'
];
}
$responses = $client->bulk($params);
2
3
4
5
6
7
8
9
10
11
12
13
14
$params = ['body' => []];
for ($i = 1; $i <= 1234567; $i++) {
$params['body'][] = [
'index' => [
'_index' => 'my_index',
'_id' => $i
]
];
$params['body'][] = [
'my_field' => 'my_value',
'second_field' => 'some more values'
];
// Every 1000 documents stop and send the bulk request
if ($i % 1000 == 0) {
$responses = $client->bulk($params);
// erase the old bulk request
$params = ['body' => []];
// unset the bulk response when you are done to save memory
unset($responses);
}
}
// Send the last batch if it exists
if (!empty($params['body'])) {
$responses = $client->bulk($params);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 5.3.3 获取文档
$params = [
'index' => 'my_index',
'id' => 'my_id'
];
// Get doc at /my_index/_doc/my_id
$response = $client->get($params);
2
3
4
5
6
7
# 5.3.4 更新文档
部分文档更新
$params = [
'index' => 'my_index',
'id' => 'my_id',
'body' => [
'doc' => [
'new_field' => 'abc'
]
]
];
// Update doc at /my_index/_doc/my_id
$response = $client->update($params);
2
3
4
5
6
7
8
9
10
11
12
脚本化文档更新
有时您需要执行脚本更新,例如递增计数器 或将新值附加到数组。 要执行脚本化更新,您需要 提供一个脚本和一组参数:
$params = [
'index' => 'my_index',
'id' => 'my_id',
'body' => [
'script' => 'ctx._source.counter += count',
'params' => [
'count' => 4
]
]
];
$response = $client->update($params);
2
3
4
5
6
7
8
9
10
11
12
Upserts
Upserts 是“更新或插入”操作。 这意味着 upsert 尝试运行 您的更新脚本,但如果文档不存在(或您所在的字段) 尝试更新不存在),而是插入默认值。
$params = [
'index' => 'my_index',
'id' => 'my_id',
'body' => [
'script' => [
'source' => 'ctx._source.counter += params.count',
'params' => [
'count' => 4
],
],
'upsert' => [
'counter' => 1
],
]
];
$response = $client->update($params);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 5.3.5 删除文档
$params = [
'index' => 'my_index',
'id' => 'my_id'
];
// Delete doc at /my_index/_doc_/my_id
$response = $client->delete($params);
2
3
4
5
6
7
# 6.demo
<?php
/**
* Description:this is description
* User:ligan
* Date:2021/1/22
* Time:10:58 上午
*/
include_once __DIR__ . "/vendor/autoload.php";
class ES7
{
private \Elasticsearch\Client $client;
public function __construct()
{
$hosts = [
'http://elastic:Ligan190318@@es-cn-zvp2d26r1000os1tn.public.elasticsearch.aliyuncs.com:9200',
// "http://47.100.249.137:9200"
// "http://47.100.212.85:9200"
];
$this->client = Elasticsearch\ClientBuilder::create()->setHosts($hosts)->build();
}
/**
* 创建索引
* User:gan
* Date:2021/1/22
* Time:11:06 上午
* @param $index
* @param $body
* @return mixed
*/
function createIndex($index, $body)
{
// $body = [
// 'settings' => [
// 'number_of_shards' => 2,
// 'number_of_replicas' => 0,
// "blocks" => [
// "read_only_allow_delete" => false
// ],
// 'analysis' => [
// 'filter' => [
// 'shingle' => [
// 'type' => 'shingle'
// ]
// ],
// 'char_filter' => [
// 'pre_negs' => [
// 'type' => 'pattern_replace',
// 'pattern' => '(\\w+)\\s+((?i:never|no|nothing|nowhere|noone|none|not|havent|hasnt|hadnt|cant|couldnt|shouldnt|wont|wouldnt|dont|doesnt|didnt|isnt|arent|aint))\\b',
// 'replacement' => '~$1 $2'
// ],
// 'post_negs' => [
// 'type' => 'pattern_replace',
// 'pattern' => '\\b((?i:never|no|nothing|nowhere|noone|none|not|havent|hasnt|hadnt|cant|couldnt|shouldnt|wont|wouldnt|dont|doesnt|didnt|isnt|arent|aint))\\s+(\\w+)',
// 'replacement' => '$1 ~$2'
// ]
// ],
// 'analyzer' => [
// 'reuters' => [
// 'type' => 'custom',
// 'tokenizer' => 'standard',
// 'filter' => ['lowercase', 'stop', 'kstem']
// ]
// ]
// ]
// ],
// 'mappings' => [
// 'properties' => [
// 'title' => [
// 'type' => 'text',
// 'analyzer' => 'reuters',
// 'copy_to' => 'combined'
// ],
// 'body' => [
// 'type' => 'text',
// 'analyzer' => 'reuters',
// 'copy_to' => 'combined'
// ],
// 'combined' => [
// 'type' => 'text',
// 'analyzer' => 'reuters'
// ],
// 'topics' => [
// 'type' => 'keyword'
// ],
// 'places' => [
// 'type' => 'keyword'
// ],
// 'user_id' => [
// 'type' => 'integer'
// ],
// 'create_time' => [
// 'type' => 'integer'
// ],
// ]
// ]
// ];
$params = [
'index' => $index,
'body' => $body
];
return $this->client->indices()->create($params);
}
/**
* 修改setting
* User:gan
* Date:2021/1/22
* Time:11:14 上午
* @param $index
* @param $body
* @return mixed
*/
public function putSettings($index, $body)
{
$params = [
'index' => $index,
'body' => $body
];
return $this->client->indices()->putSettings($params);
}
/**
* 删除索引
* User:gan
* Date:2021/1/22
* Time:11:15 上午
* @param $index
* @return mixed
*/
function deleteIndex($index)
{
$params = ['index' => $index];
return $this->client->indices()->delete($params);
}
/**
* 添加文档
* User:gan
* Date:2021/1/22
* Time:11:18 上午
* @param $index
* @param $id
* @param $body
* @return mixed
*/
function createDocument($index, $id, $body)
{
$params = [
'index' => $index,
'id' => $id,
'body' => $body
];
return $this->client->index($params);
}
function updateDocument($index, $id, $body)
{
$params = [
'index' => $index,
'id' => $id,
'body' => [
'doc' => $body
]
];
return $this->client->update($params);
}
/**
* 删除文档
* User:gan
* Date:2021/1/22
* Time:11:18 上午
* @param $index
* @param $id
* @return mixed
*/
function deleteDocument($index, $id)
{
$params = [
'index' => $index,
'id' => $id,
];
return $this->client->delete($params);
}
/**
* 修改mapping
* User:gan
* Date:2021/1/22
* Time:11:14 上午
* @param $index
* @param $properties
* @return mixed
*/
function putMapping($index, $properties)
{
$params = [
'index' => $index,
'body' => [
'_source' => [
'enabled' => true
],
'properties' => $properties
]
];
return $this->client->indices()->putMapping($params);
}
/**
* 生成测试数据
* User:gan
* Date:2021/1/22
* Time:11:06 上午
* @param $index
* @param int $num
* @return mixed
*/
function makeBatchTestData($index, $num = 10000)
{
$params = [];
for ($i = 0; $i < $num; $i++) {
$params['body'][] = [
'index' => [
'_index' => $index,
'_id' => uniqid() . $i . (10000 * microtime(true))
]
];
$params['body'][] = [
"title" => \EasySwoole\Utility\Random::makeUUIDV4(),
"body" => \EasySwoole\Utility\Random::makeUUIDV4(),
"combined" => \EasySwoole\Utility\Random::makeUUIDV4(),
"topics" => \EasySwoole\Utility\Random::makeUUIDV4(),
"places" => \EasySwoole\Utility\Random::makeUUIDV4(),
"user_id" => rand(1, 9999),
"create_time" => time()
];
}
return $this->client->bulk($params);
}
/**
* 分页查询
* User:gan
* Date:2021/1/22
* Time:11:14 上午
* 测试demo {"from":"0","size":"10","query":{"bool":{"must":[{"term":{"user_id":"8267"}},{"range":{"create_time":{"lte":"1632646837","gte":"1630646837"}}}],"must_not":[],"should":[]}},"sort":{"create_time":{"order":"desc"}},"_source":["title","create_time"]}
* @param string $index 索引名称
* @param array $query 查询条件
* @param int $from 查询开始索引值
* @param int $size 查询大小
* @param array $source 查询出来的字段
* @param array $sort 排序 "sort": [{ "date": { "order": "desc" }},{ "_score": { "order": "desc" }}]
* @param array $aggs 聚合
* @return mixed
*/
function pageSearch($index, $query, $from = 0, $size = 10, $source = [], $sort = [], $aggs = [])
{
$params = [
"index" => $index,
"from" => $from,
"size" => $size,
"_source" => $source,
"sort" => $sort,
"body" => [
"query" => $query
]
];
if (!empty($aggs)) {
$params["aggs"] = $aggs;
}
return $this->client->search($params);
}
}
try {
$a = microtime(true);
$obj = new ES7();
//var_dump($obj->createIndex("user"));
//var_dump($obj->deleteIndex("user"));
//
//var_dump($obj->putSettings("user",["blocks"=>["read_only_allow_delete"=>false]]));
//
$obj->makeBatchTestData("user", 100000);
// for ($i=0;$i<1;$i++) {
// //var_dump($obj->makeBatchTestData("user", 100000));
// //sleep(60);
// }
// var_dump(microtime(true)-$a);
// for ($i = 1; $i <= 100; $i++) {
// go(function () use ($obj, $i) {
$map = [
"bool" => [
"must" => [
[
"term" => [
"user_id" => 7691,
]
],
[
"range" => [
"create_time" => [
"gte" => 1632640066,
"lte" => 1632649799
]
]
]
],
"must_not" => [],
"should" => [],
]
];
//
// $data = $obj->pageSearch("user", $map, ($i - 1) * 4, 4);
// file_put_contents("./test/{$i}.txt", "\n" . json_encode($data) . "\n", FILE_APPEND);
// });
// }
var_dump(microtime(true) - $a);
} catch (\Throwable $e) {
var_dump($e->getMessage());
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
# 7.常见问题
# 7.1 index [user] blocked by: [FORBIDDEN/12/index read-only / allow delete (api)];
这时就是因为你的磁盘空间不足导致的,查看官方文档,可以看到当磁盘的使用率超过95%时,Elasticsearch为了防止节点耗尽磁盘空间,自动将索引设置为只读模式。
解决方法: 1、最简单也是最直接的是清理磁盘空间 2、更改elasticsearch.yml配置文件,在config/elasticsearch.yml中增加下面这句话
cluster.routing.allocation.disk.watermark.flood_stage: 99%
这是把控制洪水阶段水印设置为99%,你也可以自己设置其他百分比,默认是95%。 3、更改elasticsearch.yml配置文件,在config/elasticsearch.yml中增加下面这句话
cluster.routing.allocation.disk.threshold_enabled: false
默认为true。设置为false禁用磁盘分配决策程序。 上面无论哪一种方法修改之后,都需要重启elasticsearch,然后再把索引的read_only_allow_delete设置为false,采用一中的方法中的任意一种即可,更改后再查看索引的信息,如图,read_only_allow_delete配置没有了,表示以及设置成功了。