搜索操作

编辑

好吧……它被称为 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"}}}



搜索结果遵循与 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 数组和对象

更复杂的示例

编辑

让我们构建一个稍微复杂的示例:一个包含过滤器和查询的布尔查询。这在 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,用于继续遍历命中结果。

有关滚动的更多详细信息,请参阅参考文档

这是一个可以作为更高级操作模板的示例

$client = ClientBuilder::create()->build();
$params = [
    'scroll' => '30s',          // how long between scroll requests. should be small!
    'size'   => 50,             // how many results *per shard* you want back
    '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'        // and the same timeout window
        ]
    ]);
}