Elasticsearch支持兩種類型的查詢:基本查詢和復合查詢。 基本查詢,如詞條查詢用於查詢實際數據。 復合查詢,如布爾查詢,可以合並多個查詢, 然而,這不是全部。除了這兩種類型的查詢,你還可以用過濾查詢,根據一定的條件縮小查詢結果。不像其他查詢,篩選查詢不會影響得分,而且通常非常高效。 更加復雜的情況,查詢可以包含其他查詢。此外,一些查詢可以包含過濾器,而其他查詢可同時包含查詢和過濾器。這並不是全部,但暫時先解釋這些工作。
1.簡單查詢
這種查詢方式很簡單,但比較局限。 查詢last_name字段中含有smith一詞的文檔,可以這樣寫:
http://127.0.0.1:9200/megacorp/employee/_search
{
"query" : { "query_string" : { "query" : "last_name:smith" } } }
返回格式如下:
{
"took": 15, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 2, "max_score": 0.30685282, "hits": [ { "_index": "megacorp", "_type": "employee", "_id": "2", "_score": 0.30685282, "_source": { "first_name": "Jane", "last_name": "Smith", "age": 32, "about": "I like to collect rock albums", "interests": [ "music" ] } }, { "_index": "megacorp", "_type": "employee", "_id": "1", "_score": 0.30685282, "_source": { "first_name": "John", "last_name": "Smith", "age": 25, "about": "I love to go rock climbing", "interests": [ "sports", "music" ] } } ] } }
pretty=true參數會讓Elasticsearch以更容易閱讀的方式返回響應。
2.分頁和結果集大小(form、size)
Elasticsearch能控制想要的最多結果數以及想從哪個結果開始。下面是可以在請求體中添加的兩個額外參數。 from:該屬性指定我們希望在結果中返回的起始文檔。它的默認值是0,表示想要得到從第一個文檔開始的結果。 size:該屬性指定了一次查詢中返回的最大文檔數,默認值為10。如果只對切面結果感興趣,並不關心文檔本身,可以把這個參數設置成0。 如果想讓查詢從第2個文檔開始返回20個文檔,可以發送如下查詢:
{
"version" : true,//返回版本號 "from" : 1,//從哪個文檔開始(數組所以有0) "size" : 20,//返回多少個文檔 "query" : { "query_string" : { "query" : "last_name:smith" } } }
選擇返回字段(fields)
只返回age,about和last_name字段
{
"fields":[ "age", "about","last_name" ], "query" : { "query_string" : { "query" : "last_name:Smith" } } }
返回格式如下:
{
"took": 3, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 2, "max_score": 0.30685282, "hits": [ { "_index": "megacorp", "_type": "employee", "_id": "2", "_score": 0.30685282, "fields": { "about": [ "I like to collect rock albums" ], "last_name": [ "Smith" ], "age": [ 32 ] } }, { "_index": "megacorp", "_type": "employee", "_id": "1", "_score": 0.30685282, "fields": { "about": [ "I love to go rock climbing" ], "last_name": [ "Smith" ], "age": [ 25 ] } } ] } }
- 如果沒有定義fields數組,它將用默認值,如果有就返回_source字段;
- 如果使用_source字段,並且請求一個沒有存儲的字段,那么這個字段將從_source字段中提取(然而,這需要額外的處理);
- 如果想返回所有的存儲字段,只需傳入星號()作為字段名字。 *從性能的角度,返回_source字段比返回多個存儲字段更好。
部分字段(include、exclude)
Elasticsearch公開了部分字段對象的include和exclude屬性,所以可以基於這些屬性來包含或排除字段。例如,為了在查詢中包括以titl開頭且排除以chara開頭的字段,發出以下查詢:
{
"partial_fields" : { "partial1" : { "include" : [ "titl*" ], "exclude" : [ "chara*" ] } }, "query" : { "query_string" : { "query" : "title:crime" } } }
腳本字段(script_fields)
在JSON的查詢對象中加上script_fields部分,添加上每個想返回的腳本值的名字。若要返回一個叫correctYear的值,它用year字段減去1800計算得來,運行以下查詢:
{
"script_fields" : { "correctYear" : { "script" : "doc['year'].value - 1800" } }, "query" : { "query_string" : { "query" : "title:crime" } } }
上面的示例中使用了doc符號,它讓我們捕獲了返回結果,從而讓腳本執行速度更快,但也導致了更高的內存消耗,並且限制了只能用單個字段的單個值。如果關心內存的使用,或者使用的是更復雜的字段值,可以用_source字段。使用此字段的查詢如下所示
{
"script_fields" : { "correctYear" : { "script" : "_source.year - 1800" } }, "query" : { "query_string" : { "query" : "title:crime" } } }
返回格式如下:
{
"took" : 1, "timed_out" : false, "_shards" : { "total" : 5, "successful" : 5, "failed" : 0 }, "hits" : { "total" : 1, "max_score" : 0.15342641, "hits" : [ { "_index" : "library", "_type" : "book", "_id" : "4", "_score" : 0.15342641, "fields" : { "correctYear" : [ 86 ] } } ] } }
傳參數到腳本字段中(script_fields)
一個腳本字段的特性:可傳入額外的參數。可以使用一個變量名稱,並把值傳入params節中,而不是直接把1800寫在等式中。這樣做以后,查詢將如下所示:
{
"script_fields" : { "correctYear" : { "script" : "_source.year - paramYear", "params" : { "paramYear" : 1800 } } }, "query" : { "query_string" : { "query" : "title:crime" } } }
基本查詢
單詞條查詢:
最簡單的詞條查詢如下所示:
{
"query" : { "term" : { "last_name" : "smith" } } }
多詞條查詢:
假設想得到所有在tags字段中含有novel或book的文檔。運行以下查詢來達到目的:
{
"query" : { "terms" : { "tags" : [ "novel", "book" ], "minimum_match" : 1 } } }
上述查詢返回在tags字段中包含一個或兩個搜索詞條的所有文檔.minimum_match屬性設置為1;這意味着至少有1個詞條應該匹配。如果想要查詢匹配所有詞條的文檔,可以把minimum_match屬性設置為2。
match_all 查詢
如果想得到索引中的所有文檔,只需運行以下查詢:
{
"query" : { "match_all" : {} } }
match 查詢
{
"query" : { "match" : { "title" : "crime and punishment" } } }
上面的查詢將匹配所有在title字段含有crime、and或punishment詞條的文檔。
match查詢的幾種類型
1 布爾值匹配查詢(operator)
{
"query" : { "match" : { "title" : { "query" : "crime and punishment", "operator" : "and" } } } }
operator參數可接受or和and,用來決定查詢中的所有條件的是or還是and。
2 match_phrase查詢(slop)
這個可以查詢類似 a+x+b,其中x是未知的。即知道了a和b,x未知的結果也可以查詢出來。
{
"query" : { "match_phrase" : { "title" : { "query" : "crime punishment", "slop" : 1 } } } }
注意,我們從查詢中移除了and一詞,但因為slop參數設置為1,它仍將匹配我們的文檔。
slop:這是一個整數值,該值定義了文本查詢中的詞條和詞條之間可以有多少個未知詞條,以被視為跟一個短語匹配。此參數的默認值是0,這意味着,不允許有額外的詞條,即上面的x可以是多個。
3 match_phrase_prefix查詢
{
"query" : { "match_phrase_prefix" : { "title" : { "query" : "crime and punishm", "slop" : 1, "max_expansions" : 20 } } } }
注意,我們沒有提供完整的“crime and punishment”短語,而只是提供“crime and punishm”,該查詢仍將匹配我們的文檔。
multi_match 查詢
multi_match查詢和match查詢一樣,但是可以通過fields參數針對多個字段查詢。當然,match查詢中可以使用的所有參數同樣 可以在multi_match查詢中使用。所以,如果想修改match查詢,讓它針對title和otitle字段運行,那么運行以下查詢:
{
"query" : { "multi_match" : { "query" : "crime punishment", "fields" : [ "title", "otitle" ] } } }
前綴查詢
想找到所有title字段以cri開始的文檔,可以運行以下查詢:
{
"query" : { "prefix" : { "title" : "cri" } } }
通配符查詢
這里?表示任意字符:
{
"query" : { "wildcard" : { "title" : "cr?me" } } }
范圍查詢
- gte:范圍查詢將匹配字段值大於或等於此參數值的文檔。
- gt:范圍查詢將匹配字段值大於此參數值的文檔。
- lte:范圍查詢將匹配字段值小於或等於此參數值的文檔。
- lt:范圍查詢將匹配字段值小於此參數值的文檔。
舉例來說,要找到year字段從1700到1900的所有圖書,可以運行以下查詢:
{
"query" : { "range" : { "year" : { "gte" : 1700, "lte" : 1900 } } } }
復合查詢
布爾查詢
- should:被它封裝的布爾查詢可能被匹配,也可能不被匹配。被匹配的should節點數由minimum_should_match參數控制。
- must:被它封裝的布爾查詢必須被匹配,文檔才會返回。
- must_not:被它封裝的布爾查詢必須不被匹配,文檔才會返回。
假設我們想要找到所有這樣的文檔:在title字段中含有crime詞條,並且year字段可以在也可以不在1900~2000的范圍里,在otitle字段中不可以包含nothing詞條。用布爾查詢的話,類似於下面的代碼:
{
"query" : { "bool" : { "must" : { "term" : { "title" : "crime" } }, "should" : { "range" : { "year" : { "from" : 1900, "to" : 2000 } } }, "must_not" : { "term" : { "otitle" : "nothing" } } } } }
過濾器(不太理解過濾器的作用)
返回給定title的所有文檔,但結果縮小到僅在1961年出版的書。使用filtered查詢。如下:
{
"query": { "filtered" : { "query" : { "match" : { "title" : "Catch-22" } }, "filter" : { "term" : { "year" : 1961 } } } } }
Demo
1.查詢wechat_customer表中mid等於$mid,且subscribe=1的人。
http://localhost:9200/wechat_v6_count/wechat_customer/_search?search_type=count
//php代碼 $esjson = array(); $esjson['query']['bool']['must'][] = array("term" => array("mid" => $mid)); $esjson['query']['bool']['must'][] = array("term" => array("subscribe" => 1)); $esjson['aggs'] = array("type_count" => array("value_count" => array("field" => "id")));
{
"query":{ "bool":{ "must":[ { "term":{"mid":"55"} },{ "term":{"subscribe":1} }] } }, "aggs":{ "type_count":{ "value_count":{"field":"id"} } } }
2.查詢wechat_customer 中mid等於$mid,$rule大於等於$start,且subscribe等於1的人數。(聚合默認返回的條數為10,如果加上size等於0的參數則返回所有)
$esjson['query']['bool']['must'][] = array("range" => array($rule => array("gte"=>$start))); $esjson['query']['bool']['must'][] = array("term" => array("mid" => $mid)); $esjson['query']['bool']['must'][] = array("term" => array("subscribe" => 1)); $esjson['aggs'] = array("type_count" => array("value_count" => array("field" => "id"))); $esjson = json_encode($esjson); $esresult = ElasticsearchClient::searchForCount($esjson); $result = $esresult['aggregations']['type_count']['value']; //原來的sql //$sql = "SELECT count(*) as 'cnt' from wechat_customer where mid =:mid AND " . $rule . ">=:start AND subscribe=1;"; //$params = array(':mid' => $mid, ':start' => $start);
esjson
{
"query":{ "bool":{ "must":[ { "range":{ "action_count":{"gte":"15"} } }, { "term":{"mid":"55"} }, { "term":{"subscribe":"1"} } ] } }, "aggs":{ "type_count":{ "value_count":{"field":"id"} } } }