索引文档
当你向 Elasticsearch 添加文档时,可以索引 JSON 文档。这自然映射到 PHP 的关联数组,因为它们很容易的用 JSON 编码。因此,在 Elasticsearch-PHP 中你可以创建关联数组并将其传给客户端进行索引。有几种方法可以将数据提取到 Elasticsearch 中,这里我们都将会介绍
单文档索引
当你查找文档时,你可以提供一个 ID 或者让 elasticsearch 给你生成一个 ID。
提供 ID 值
$params = [
'index' => 'my_index',
'type' => 'my_type',
'id' => 'my_id',
'body' => [ 'testField' => 'abc']
];
// Document will be indexed to my_index/my_type/my_id
$response = $client->index($params);
省略 ID 值
$params = [
'index' => 'my_index',
'type' => 'my_type',
'body' => [ 'testField' => 'abc']
];
// Document will be indexed to my_index/my_type/<autogenerated ID>
$response = $client->index($params);
如果你需要设置其他参数,例如 routing
值,你可以在 index
,type
等旁边指定数组中的那些参数。例如,我们可以在新的文档中设置路由和时间戳:
附加参数
$params = [
'index' => 'my_index',
'type' => 'my_type',
'id' => 'my_id',
'routing' => 'company_xyz',
'timestamp' => strtotime("-1d"),
'body' => [ 'testField' => 'abc']
];
$response = $client->index($params);
批量索引
Elasticsearch 也支持批量索引文档。 批量 API 需要提供 JSON 格式的 action/元数据对,由换行符分割。 当在 PHP 中构建文档也是相似的, 首先创造一个 axtion 数组对象 (例如 index
对象), 然后你还要创建一个 body 对象。而 PHP 程序则重复上述操作构建文档数据。
一个简单的例子如下所示:
使用 PHP 数组批量索引
for($i = 0; $i < 100; $i++) {
$params['body'][] = [
'index' => [
'_index' => 'my_index',
'_type' => 'my_type',
]
];
$params['body'][] = [
'my_field' => 'my_value',
'second_field' => 'some more values'
];
}
$responses = $client->bulk($params);
实际上在一次 bulk 请求中发送数量会比文档实际数量少。如果是这种情况,您需要对请求进行批处理并定期发送:
批量索引与批次
$params = ['body' => []];
for ($i = 1; $i <= 1234567; $i++) {
$params['body'][] = [
'index' => [
'_index' => 'my_index',
'_type' => 'my_type',
'_id' => $i
]
];
$params['body'][] = [
'my_field' => 'my_value',
'second_field' => 'some more values'
];
// 每 1000 个文件 停止并批量发送请求
if ($i % 1000 == 0) {
$responses = $client->bulk($params);
// 删除旧的批量请求
$params = ['body' => []];
// 为了节约内存,在完成时取消批量响应
unset($responses);
}
}
// 如果最后一批存在,那么就发送
if (!empty($params['body'])) {
$responses = $client->bulk($params);
}
获取文档
Elasticsearch 提供了实时获取文档。这意味着只要文档被编入索引并且在客户端得到确认,您可以从任何分片中检索文档。 通过它的完整 索引/类型/id
路径请求文档来执行获取操作:
$params = [
'index' => 'my_index',
'type' => 'my_type',
'id' => 'my_id'
];
// 在 /my_index/my_type/my_id 中获取文档
$response = $client->get($params);
更新文档
更新文档允许您完全替换现有的文档,或者仅仅更新某些字段(更改现有字段或者添加新字段)。
部分文档更新
如果要更新部分文档(例如,更改现有字段或者添加新字段)你可以在 body
参数中指定 doc
来实现。这会将 doc
中的字段与现有文档合并。
$params = [
'index' => 'my_index',
'type' => 'my_type',
'id' => 'my_id',
'body' => [
'doc' => [
'new_field' => 'abc'
]
]
];
// 在 /my_index/my_type/my_id 中更新文档
$response = $client->update($params);
脚本文档更新
有时候您需要执行脚本更新,比如计数器的递增或者在一个数组添加一个新值。为了执行脚本更新,您需要提供一份脚本和(通常)一系列参数:
$params = [
'index' => 'my_index',
'type' => 'my_type',
'id' => 'my_id',
'body' => [
'script' => 'ctx._source.counter += count',
'params' => [
'count' => 4
]
]
];
$response = $client->update($params);
Upserts
Upserts 是 "更新或插入" 操作。这意味着 upsert 将尝试运行您的更新脚本,但是如果文档不存在(或者您尝试去更新的字段不存在),则将插入默认值。
$params = [
'index' => 'my_index',
'type' => 'my_type',
'id' => 'my_id',
'body' => [
'script' => [
'source' => 'ctx._source.counter += params.count',
'params' => [
'count' => 4
],
],
'upsert' => [
'counter' => 1
],
]
];
$response = $client->update($params);
删除文件
最后,你可以通过指定完整的 /index/type/id
路径来删除文档:
$params = [
'index' => 'my_index',
'type' => 'my_type',
'id' => 'my_id'
];
// 删除 /my_index/my_type/my_id 目录下的文件
$response = $client->delete($params);