索引文档

当你向 Elasticsearch 添加文档时,可以索引 JSON 文档。这自然映射到 PHP 的关联数组,因为它们很容易的用 JSON 编码。因此,在 Elasticsearch-PHP 中你可以创建关联数组并将其传给客户端进行索引。有几种方法可以将数据提取到 Elasticsearch 中,这里我们都将会介绍

单文档索引

当你查找文档时,你可以提供一个 ID 或者让 elasticsearch 给你生成一个 ID。

提供 ID 值

  1. $params = [
  2. 'index' => 'my_index',
  3. 'type' => 'my_type',
  4. 'id' => 'my_id',
  5. 'body' => [ 'testField' => 'abc']
  6. ];
  7. // Document will be indexed to my_index/my_type/my_id
  8. $response = $client->index($params);

省略 ID 值

  1. $params = [
  2. 'index' => 'my_index',
  3. 'type' => 'my_type',
  4. 'body' => [ 'testField' => 'abc']
  5. ];
  6. // Document will be indexed to my_index/my_type/<autogenerated ID>
  7. $response = $client->index($params);

如果你需要设置其他参数,例如 routing 值,你可以在 indextype 等旁边指定数组中的那些参数。例如,我们可以在新的文档中设置路由和时间戳:

附加参数

  1. $params = [
  2. 'index' => 'my_index',
  3. 'type' => 'my_type',
  4. 'id' => 'my_id',
  5. 'routing' => 'company_xyz',
  6. 'timestamp' => strtotime("-1d"),
  7. 'body' => [ 'testField' => 'abc']
  8. ];
  9. $response = $client->index($params);

批量索引

Elasticsearch 也支持批量索引文档。 批量 API 需要提供 JSON 格式的 action/元数据对,由换行符分割。 当在 PHP 中构建文档也是相似的, 首先创造一个 axtion 数组对象 (例如 index 对象), 然后你还要创建一个 body 对象。而 PHP 程序则重复上述操作构建文档数据。

一个简单的例子如下所示:

使用 PHP 数组批量索引

  1. for($i = 0; $i < 100; $i++) {
  2. $params['body'][] = [
  3. 'index' => [
  4. '_index' => 'my_index',
  5. '_type' => 'my_type',
  6. ]
  7. ];
  8. $params['body'][] = [
  9. 'my_field' => 'my_value',
  10. 'second_field' => 'some more values'
  11. ];
  12. }
  13. $responses = $client->bulk($params);

实际上在一次 bulk 请求中发送数量会比文档实际数量少。如果是这种情况,您需要对请求进行批处理并定期发送:

批量索引与批次

  1. $params = ['body' => []];
  2. for ($i = 1; $i <= 1234567; $i++) {
  3. $params['body'][] = [
  4. 'index' => [
  5. '_index' => 'my_index',
  6. '_type' => 'my_type',
  7. '_id' => $i
  8. ]
  9. ];
  10. $params['body'][] = [
  11. 'my_field' => 'my_value',
  12. 'second_field' => 'some more values'
  13. ];
  14. // 每 1000 个文件 停止并批量发送请求
  15. if ($i % 1000 == 0) {
  16. $responses = $client->bulk($params);
  17. // 删除旧的批量请求
  18. $params = ['body' => []];
  19. // 为了节约内存,在完成时取消批量响应
  20. unset($responses);
  21. }
  22. }
  23. // 如果最后一批存在,那么就发送
  24. if (!empty($params['body'])) {
  25. $responses = $client->bulk($params);
  26. }

获取文档

Elasticsearch 提供了实时获取文档。这意味着只要文档被编入索引并且在客户端得到确认,您可以从任何分片中检索文档。 通过它的完整 索引/类型/id 路径请求文档来执行获取操作:

  1. $params = [
  2. 'index' => 'my_index',
  3. 'type' => 'my_type',
  4. 'id' => 'my_id'
  5. ];
  6. // 在 /my_index/my_type/my_id 中获取文档
  7. $response = $client->get($params);

更新文档

更新文档允许您完全替换现有的文档,或者仅仅更新某些字段(更改现有字段或者添加新字段)。

部分文档更新

如果要更新部分文档(例如,更改现有字段或者添加新字段)你可以在 body 参数中指定 doc 来实现。这会将 doc 中的字段与现有文档合并。

  1. $params = [
  2. 'index' => 'my_index',
  3. 'type' => 'my_type',
  4. 'id' => 'my_id',
  5. 'body' => [
  6. 'doc' => [
  7. 'new_field' => 'abc'
  8. ]
  9. ]
  10. ];
  11. // 在 /my_index/my_type/my_id 中更新文档
  12. $response = $client->update($params);

脚本文档更新

有时候您需要执行脚本更新,比如计数器的递增或者在一个数组添加一个新值。为了执行脚本更新,您需要提供一份脚本和(通常)一系列参数:

  1. $params = [
  2. 'index' => 'my_index',
  3. 'type' => 'my_type',
  4. 'id' => 'my_id',
  5. 'body' => [
  6. 'script' => 'ctx._source.counter += count',
  7. 'params' => [
  8. 'count' => 4
  9. ]
  10. ]
  11. ];
  12. $response = $client->update($params);

Upserts

Upserts 是 "更新或插入" 操作。这意味着 upsert 将尝试运行您的更新脚本,但是如果文档不存在(或者您尝试去更新的字段不存在),则将插入默认值。

  1. $params = [
  2. 'index' => 'my_index',
  3. 'type' => 'my_type',
  4. 'id' => 'my_id',
  5. 'body' => [
  6. 'script' => [
  7. 'source' => 'ctx._source.counter += params.count',
  8. 'params' => [
  9. 'count' => 4
  10. ],
  11. ],
  12. 'upsert' => [
  13. 'counter' => 1
  14. ],
  15. ]
  16. ];
  17. $response = $client->update($params);

删除文件

最后,你可以通过指定完整的 /index/type/id 路径来删除文档:

  1. $params = [
  2. 'index' => 'my_index',
  3. 'type' => 'my_type',
  4. 'id' => 'my_id'
  5. ];
  6. // 删除 /my_index/my_type/my_id 目录下的文件
  7. $response = $client->delete($params);