搜索操作
嗯...Elasticsearch 之名并非空穴来风!让我们来谈谈客户端中的搜索操作。
客户端让您可以完全访问 REST API 公开的每个查询和参数,尽可能遵循命名方案。让我们看一些示例,以便您熟悉语法。
这是一个匹配查询的标准 curl 示例
curl -XGET 'localhost:9200/my_index/_search' -d '{
"query" : {
"match" : {
"testField" : "abc"
}
}
}'
以下是在客户端中构建的相同查询
$params = [
'index' => 'my_index',
'body' => [
'query' => [
'match' => [
'testField' => 'abc'
]
]
]
];
$results = $client->search($params);
请注意,PHP 数组的结构和布局与 JSON 请求体相同。这使得将 JSON 示例转换为 PHP 变得非常简单。检查 PHP 数组(对于更复杂的示例)的一种快速方法是将其编码回 JSON 并进行检查
$params = [
'index' => 'my_index',
'body' => [
'query' => [
'match' => [
'testField' => 'abc'
]
]
]
];
print_r(json_encode($params['body']));
{"query":{"match":{"testField":"abc"}}}
有时出于测试目的或从其他系统迁移时,使用原始 JSON 会很方便。您可以在请求体中将原始 JSON 作为字符串使用,客户端会自动检测到这一点
$json = '{
"query" : {
"match" : {
"testField" : "abc"
}
}
}';
$params = [
'index' => 'my_index',
'body' => $json
];
$results = $client->search($params);
搜索结果遵循与 Elasticsearch 搜索响应相同的格式,唯一的区别是将 JSON 响应反序列化回 PHP 数组。处理搜索结果就像遍历数组值一样简单
$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'];
使用客户端可以轻松构建布尔查询。例如,以下查询
curl -XGET 'localhost:9200/my_index/_search' -d '{
"query" : {
"bool" : {
"must": [
{
"match" : { "testField" : "abc" }
},
{
"match" : { "testField2" : "xyz" }
}
]
}
}
}'
将按如下方式构建(注意方括号的位置)
$params = [
'index' => 'my_index',
'body' => [
'query' => [
'bool' => [
'must' => [
[ 'match' => [ 'testField' => 'abc' ] ],
[ 'match' => [ 'testField2' => 'xyz' ] ],
]
]
]
]
];
$results = $client->search($params);
请注意,`must` 子句接受一个数组的数组。这在内部被序列化为一个 JSON 对象数组,因此最终的输出与 curl 示例相同。有关 PHP 中数组和对象的更多详细信息,请参阅 在 PHP 中处理 JSON 数组和对象。
让我们构建一个稍微复杂一些的示例:一个同时包含 filter 和 query 的布尔查询。这在 Elasticsearch 查询中是一项非常常见的活动,因此将是一个很好的演示。
查询的 curl 版本
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' => [
'query' => [
'bool' => [
'filter' => [
'term' => [ 'my_field' => 'abc' ]
],
'should' => [
'match' => [ 'my_other_field' => 'xyz' ]
]
]
]
]
];
$results = $client->search($params);
Elasticsearch 的滚动功能用于批量分页处理大量文档,例如导出属于单个用户的所有文档。它比常规搜索更高效,因为它无需维护昂贵的优先级队列来对文档进行排序。
滚动的工作原理是维护索引的“时间点”快照,然后用于分页。即使存在后台索引/更新/删除,此窗口也能实现一致的分页。首先,执行一个启用 `scroll` 的搜索请求。这将返回一“页”文档以及一个 `scroll_id`,该 `scroll_id` 用于继续遍历命中文档。
有关滚动的更多详细信息,请参阅参考文档。
这是一个可以作为更高级操作模板的示例
$client = ClientBuilder::create()->build();
$params = [
'scroll' => '30s',
'size' => 50,
'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([
'body' => [
'scroll_id' => $scroll_id, //...using our previously obtained _scroll_id
'scroll' => '30s'
]
]);
}
- 两次滚动请求之间的时间间隔。应较短!
- 您希望返回*每个分片*的结果数量
- 以及相同的超时窗口