当你要在 Elasticsearch 增加文档时,你就需要索引 JSON 文档。JSON 文档会映射 PHP 关联数组,因为 PHP 关联数组可以 encode 为 JSON 数据格式。
因此在 Elasticsearch-PHP 中你可以传递关联数组给客户端来索引文档。我们会概述几种方法来增加文档到 Elasticsearch。
当索引一个文档时,你可以提供一个 ID 或者让 Elasticsearch 自动生成。
提供 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
等参数后。例如,索引一个新的文档时设置 routing 值和 timestamp 值:
$params = [
'index' => 'my_index',
'type' => 'my_type',
'id' => 'my_id',
'routing' => 'company_xyz',
'timestamp' => strtotime("-1d"),
'body' => [ 'testField' => 'abc']
];
$response = $client->index($params);
Elasticsearch 也支持批量(bulk)索引文档。bulk API 要求提供 JSON 格式的 action/元数据 键值对。在 PHP 中构建批量文档数据也是相似的。你首先要创建一个 action 数组对象(如 index
对象),然后你还要创建一个 body 对象。而 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'
];
// 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);
}
Elasticsearch 提供实时获取文档的方法。这意味着只要文档被索引且客户端收到消息确认后,你就可以立即在任何的分片中检索文档。Get 操作通过 index/type/id
方式请求一个文档信息:
$params = [
'index' => 'my_index',
'type' => 'my_type',
'id' => 'my_id'
];
// Get doc at /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'
]
]
];
// Update doc at /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 操作是指“更新或插入”操作。这意味着一个 upsert 操作会先执行 script 更新,如果文档不存在(或是你更新的字段不存在),则会插入一个默认值。
$params = [
'index' => 'my_index',
'type' => 'my_type',
'id' => 'my_id',
'body' => [
'script' => 'ctx._source.counter += count',
'params' => [
'count' => 4
],
'upsert' => [
'counter' => 1
]
]
];
$response = $client->update($params);