• 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 ElasticsearchClient();  
      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 ( rue) {  
      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. }  
  • 相关阅读:
    jquery Flexigrid只选择一行,增加双击事件,获取数据库ID
    [工具库]JOJSONBuilder工具类——一键把多个bean对象数据转换为JSON格式数据
    java 观察者模式
    [工具库]JOXMLBuilder工具类——一键把多个bean对象数据转换为XML格式数据
    JVM原理
    WEB项目的分层结构
    一刻钟精通正则表达式
    [Java]Stack栈和Heap堆的区别(终结篇)[转]
    [java]二、八、十、十六进制之间的转换
    java 适配器模式
  • 原文地址:https://www.cnblogs.com/crystaltu/p/7657352.html
Copyright © 2020-2023  润新知