加载中

搜索操作

嗯...​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 作为字符串使用,客户端会自动检测到这一点

$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'
        ]
    ]);
}
  1. 两次滚动请求之间的时间间隔。应较短!
  2. 您希望返回*每个分片*的结果数量
  3. 以及相同的超时窗口
© . All rights reserved.