Elasticsearch-PHP 搜索操作

Posted Hail Hydra

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Elasticsearch-PHP 搜索操作相关的知识,希望对你有一定的参考价值。

搜索操作

好吧,这不叫elasticsearch的不劳而获!让我们来谈谈php客户端中的搜索操作。

客户端允许你通过REST API访问所有的查询和公开的参数,尽可能的遵循命名规则。让我们来看一些例子,你就可以熟悉它的语法。

匹配查询

这里是一个标准的匹配查询的curl:

 

  1. curl -XGET ‘localhost:9200/my_index/my_type/_search‘ -d ‘{  
  2.     "query" : {  
  3.         "match" : {  
  4.             "testField" : "abc"  
  5.         }  
  6.     }  
  7. }‘  


这里是在客户端中=同样查询结构的查询:

 

 

 
  1. $params[‘index‘] = ‘my_index‘;  
  2. $params[‘type‘]  = ‘my_type‘;  
  3. $params[‘body‘][‘query‘][‘match‘][‘testField‘] = ‘abc‘;  
  4.   
  5. $results = $client->search($params);  


使用原始JSON

 

正如你看到的JSON和查询之间的转换是非常简单的。你可以直接序列化JSON到body中,或者甚至提供原始的JSON字符串。客户端会处理的很好:

 

 
  1. $json = ‘{  
  2.     "query" : {  
  3.         "match" : {  
  4.             "testField" : "abc"  
  5.         }  
  6.     }  
  7. }‘;  
  8.   
  9. $params[‘index‘] = ‘my_index‘;  
  10. $params[‘type‘]  = ‘my_type‘;  
  11. $params[‘body‘]  = $json;  
  12.   
  13. $results = $client->search($params);  

 

 

搜索结果返回的是简单的由elasticsearch响应元素序列化成的数组。与搜索结果工作就像与迭代数组一样简单:

 

 
  1. $milliseconds = $results[‘took‘];  
  2. $maxScore     = $results[‘hits‘][‘max_score‘];  
  3.   
  4. $score = $results[‘hits‘][‘hits‘][0][‘_score‘];  
  5. $doc   = $results[‘hits‘][‘hits‘][0][‘_source‘];  

 

 

Bool 查询

 

Bool查询可以使用客户端轻松的构造出来。例如这个查询:

 

 
  1. curl -XGET ‘localhost:9200/my_index/my_type/_search‘ -d ‘{  
  2.     "query" : {  
  3.         "bool" : {  
  4.             "must": {  
  5.                 "match" : {  
  6.                     "testField" : "abc"  
  7.                 },  
  8.                 "match" : {  
  9.                     "anotherTestField" : "xyz"  
  10.                 }  
  11.             }  
  12.         }  
  13.     }  
  14. }‘  

像这样的结构(注意中括号的位置)

 

 

 
  1. $params[‘index‘] = ‘my_index‘;  
  2. $params[‘type‘]  = ‘my_type‘;  
  3. $params[‘body‘][‘query‘][‘bool‘][‘must‘] = array(  
  4.     array(‘match‘ => array(‘testField‘ => ‘abc‘)),  
  5.     array(‘match‘ => array(‘anotherTestField‘ => ‘xyz‘)),  
  6. );  
  7.   
  8. $results = $client->search($params);  

 

 

一个更复杂的例子

 

让我们来构造一个稍微复杂的例子:一个过滤的查询包含一个过滤器和一个查询。这在elasticsearch查询中是非常常见的活动,所以,这将是一个好的演示。

curl版本的查询:

 

 
  1. curl -XGET ‘localhost:9200/my_index/my_type/_search‘ -d ‘{  
  2.     "query" : {  
  3.         "filtered" : {  
  4.             "filter" : {  
  5.                 "term" : {  
  6.                     "my_field" : "abc"  
  7.                 }  
  8.             },  
  9.             "query" : {  
  10.                 "match" : {  
  11.                     "my_other_field" : "xyz"  
  12.                 }  
  13.             }  
  14.         }  
  15.     }  
  16. }‘  


PHP版本的查询:

 

 

 
  1. $params[‘index‘] = ‘my_index‘;  
  2. $params[‘type‘]  = ‘my_type‘;  
  3.   
  4. $filter = array();  
  5. $filter[‘term‘][‘my_field‘] = ‘abc‘;  
  6.   
  7. $query = array();  
  8. $query[‘match‘][‘my_other_field‘] = ‘xyz‘;  
  9.   
  10. $params[‘body‘][‘query‘][‘filtered‘] = array(  
  11.     "filter" => $filter,  
  12.     "query"  => $query  
  13. );  
  14.   
  15. $results = $client->search($params);  

为了清晰和可读性,过滤器和查询部分作为变量被单独分配并且之后组合在一起。这通常对应用程序来说是一个好的设计模式,因为它可以让你对待你的查询和过滤器想构建块一样,可以通过你的应用程序传递。

 

当然,在最后,他被构建在一个简单的数组中。你可以轻松构建整个数组在一个定义的嵌套数组块中,或者一行一行的构建。

所有客户端需要一个关联数组,并且结构要和JSON查询结构匹配。

Function_Score 查询

有一点需要特别注意关于function_score 查询。由于PHP处理JSON编码,一切都被转换成了数组的这种活那种形式。这通常不是问题,因为Elasticsearch API中大多地方接受数组或互换空对象。

然而,function_score 稍有不同,需要区分空数组和空对象,例如,考虑如下查询:

 

  1. {  
  2.    "query":{  
  3.       "function_score":{  
  4.          "functions":[  
  5.             {  
  6.                "random_score":{}  
  7.             }  
  8.          ],  
  9.          "boost_mode":"replace",  
  10.          "query":{  
  11.             "match_all":{}  
  12.          }  
  13.       }  
  14.    }  
  15. }  


function_score定义一个数组对象,random_score 用空对象作为值。

 

PHP的json_encode会转换查询到这种形式:

 

 
  1. {  
  2.    "query":{  
  3.       "function_score":{  
  4.          "functions":[  
  5.             {  
  6.                "random_score":[]  
  7.             }  
  8.          ],  
  9.          "boost_mode":"replace",  
  10.          "query":{  
  11.             "match_all":[]  
  12.          }  
  13.       }  
  14.    }  
  15. }  


这样会导致一个解析异常。我们需要做的是告诉PHP random_score 包含一个空对象,不是一个数组。要做到这样,我们需要需要指定一个显式空对象:

 

 
  1. $params[‘body‘] = array(  
  2.     ‘query‘ => array(  
  3.         ‘function_score‘ => array(  
  4.             ‘functions‘ => array(  
  5.                 array("random_score" => (object) array())  
  6.             ),  
  7.             ‘query‘ => array(‘match_all‘ => array())  
  8.         )  
  9.     )  
  10. );  
  11. $results = $client->search($params);  

现在,JSON会被正常编码,不再会出现解析异常。

 

 

扫描/滚动

Elasticsearch的扫描/滚动功能类似于搜索,但在许多方面不同。它的工作方式是使用scan中的search_type执行一个搜索查询。这将启动一个扫描窗口并在扫面时保持打开。这允许真正的一致的分页。
一旦扫描窗口打开,你可能开始在窗口上滚动。这返回的结果要匹配你的查询,但顺序是随机的。这种随机的排序对性能来说是很重要的。深分页时昂贵的,当你需要通过碎片去维护一个分类的一致的排序。

 
    1. $client = new Elasticsearch\Client();  
    2. $params = array(  
    3.     "search_type" => "scan",    // use search_type=scan  
    4.     "scroll" => "30s",          // how long between scroll requests. should be small!  
    5.     "size" => 50,               // how many results *per shard* you want back  
    6.     "index" => "my_index",  
    7.     "body" => array(  
    8.         "query" => array(  
    9.             "match_all" => array()  
    10.         )  
    11.     )  
    12. );  
    13.   
    14. $docs = $client->search($params);   // Execute the search  
    15. $scroll_id = $docs[‘_scroll_id‘];   // The response will contain no results, just a _scroll_id  
    16.   
    17. // Now we loop until the scroll "cursors" are exhausted  
    18. while (\true) {  
    19.   
    20.     // Execute a Scroll request  
    21.     $response = $client->scroll(  
    22.         array(  
    23.             "scroll_id" => $scroll_id,  //...using our previously obtained _scroll_id  
    24.             "scroll" => "30s"           // and the same timeout window  
    25.         )  
    26.     );  
    27.   
    28.     // Check to see if we got any search hits from the scroll  
    29.     if (count($response[‘hits‘][‘hits‘]) > 0) {  
    30.         // If yes, Do Work Here  
    31.   
    32.         // Get new scroll_id  
    33.         // Must always refresh your _scroll_id!  It can change sometimes  
    34.         $scroll_id = $response[‘_scroll_id‘];  
    35.     } else {  
    36.         // No results, scroll cursor is empty.  You‘ve exported all the data  
    37.         break;  
    38.     }  
    39. }  






以上是关于Elasticsearch-PHP 搜索操作的主要内容,如果未能解决你的问题,请参考以下文章

Elasticsearch-PHP 索引操作2

Elasticsearch-PHP 安装

Elasticsearch-PHP 概述

Elasticsearch-PHP 快速开始

使用composer安装Elasticsearch-php教程

使用composer安装Elasticsearch-php教程