1. 程式人生 > >Elasticsearch 常用查詢語句理解

Elasticsearch 常用查詢語句理解

pretty
在任意的查詢字串中增加pretty引數,會讓Elasticsearch美化輸出(pretty-print)JSON響應以便更加容易閱讀。
GET /website/blog/123?pretty

針對性過濾輸出
GET /website/blog/123?_source=title,text

如果你想做的只是檢查文件是否存在,使用HEAD方法來代替GET。HEAD請求不會返回響應體,只有HTTP頭:
curl -i -XHEAD http://localhost:9200/website/blog/123
HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Content-Length: 0

請求成功的建立了一個新文件,Elasticsearch將返回正常的元資料且響應狀態碼是201 Created,如果文件已存在,Elasticsearch將返回409 Conflict響應狀態碼。

解決衝突:
1.在讀一行資料前鎖定這行,然後確保只有加鎖的那個執行緒可以修改這行資料。
2.在讀寫過程中資料發生了變化,更新操作將失敗。這時候由程式決定在失敗後如何解決衝突。實際情況中,可以重新嘗試更新,重新整理資料(重新讀取)或者直接反饋給使用者。

如果需要從Elasticsearch中檢索多個文件,相對於一個一個的檢索,更快的方式是在一個請求中使用multi-get或者mget API。mget是針對讀,針對所有主從分片。
POST /_mget
{
   "docs" : [
      {
         "_index" : "website",
         "_type" :  "blog",
         "_id" :    2
      },
      {
         "_index" : "website",
         "_type" :  "pageviews",
         "_id" :    1,
         "_source": "views"
      }
   ]
}

bulk API允許我們使用單一請求來實現多個文件的create、index、update或delete。針對主分片操作。
POST /_bulk
{ "create": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "title":    "Cannot create - it already exists" }
{ "index":  { "_index": "website", "_type": "blog", "_id": "123" }}
{ "title":    "But we can update it" }
整個批量請求需要被載入到接受我們請求節點的記憶體裡,所以請求越大,給其它請求可用的記憶體就越小。有一個最佳的bulk請求大小。超過這個大小,效能不再提升而且可能降低。


路由文件到分片

當你索引一個文件,它被儲存在單獨一個主分片上。Elasticsearch是如何知道文件屬於哪個分片的呢?當你建立一個新文件,它是如何知道是應該儲存在分片1還是分片2上的呢?
程序不能是隨機的,因為我們將來要檢索文件。事實上,它根據一個簡單的演算法決定:

shard = hash(routing) % number_of_primary_shards

routing值是一個任意字串,它預設是_id但也可以自定義。這個routing字串通過雜湊函式生成一個數字,然後除以主切片的數量得到一個餘數(remainder),餘數的範圍永遠是0到

number_of_primary_shards - 1,這個數字就是特定文件所在的分片。
這也解釋了為什麼主分片的數量只能在建立索引時定義且不能修改:如果主分片的數量在未來改變了,所有先前的路由值就失效了,文件也就永遠找不到了。

replication複製
複製預設的值是sync。這將導致主分片得到複製分片的成功響應後才返回。設定replication為async,請求在主分片上被執行後就會返回給客戶端。它依舊會轉發請求給複製節點,但將不知道複製

節點成功與否。

consistency
預設主分片在嘗試寫入時需要規定數量(quorum)或過半的分片(可以是主節點或複製節點)可用。
int( (primary + number_of_replicas) / 2 ) + 1  number_of_replicas是複製分片的數量。

資料檢索
1.客戶端給Node 1傳送get請求。
2.節點使用文件的_id確定文件屬於分片0。分片0對應的複製分片在三個節點上都有。負載均衡轉發請求到Node 2。
3.Node 2返回文件(document)給Node 1然後返回給客戶端。

搜尋:
hits:響應中最重要的部分是hits,它包含了total欄位來表示匹配到的文件總數,hits陣列還包含了匹配到的前10條資料。每個節點都有一個_score欄位,這是相關性得分(relevance score),

它衡量了文件與查詢的匹配程度。按照_score降序排列的
took告訴我們整個搜尋請求花費的毫秒數。
time_out值告訴我們查詢超時與否。
{
   "hits" : {
      "total" :       14,
      "hits" : [
        {
          "_index":   "us",
          "_type":    "tweet",
          "_id":      "7",
          "_score":   1,
          "_source": {
             "date":    "2014-09-17",
             "name":    "John Smith",
             "tweet":   "The Query DSL is really powerful and flexible",
             "user_id": 2
          }
       },
        ... 9 RESULTS REMOVED ...
      ],
      "max_score" :   1
   },
   "took" :           4,
   "_shards" : {
      "failed" :      0,
      "successful" :  10,
      "total" :       10
   },
   "timed_out" :      false
}

多索引和多類別:
GET /_all/tweet/_search?q=tweet:elasticsearch    _all:所有文件
/_search
在所有索引的所有型別中搜索

/gb/_search
在索引gb的所有型別中搜索

/gb,us/_search
在索引gb和us的所有型別中搜索

/g*,u*/_search
在以g或u開頭的索引的所有型別中搜索

Elasticsearch分頁展示,接受from和size引數:

size: 結果數,預設10
from: 跳過開始的結果數,預設0

如果你想每頁顯示5個結果,頁碼從1到3,那請求如下:
GET /_search?size=5
GET /_search?size=5&from=5
GET /_search?size=5&from=10

對映(mapping)機制用於進行欄位型別確認,將每個欄位匹配為一種確定的資料型別(string, number, booleans, date等)。
分析(analysis)機制用於進行全文文字(Full Text)的分詞,以建立供搜尋用的反向索引。

例:Elasticsearch在對gb索引中的tweet型別進行mapping,Elasticsearch為對欄位型別進行猜測,動態生成了欄位和型別的對映關係
date型別的欄位和string型別的欄位的索引方式是不同的,查詢匹配日期結果也是不同的。
{
   "gb": {
      "mappings": {
         "tweet": {
            "properties": {
               "date": {
                  "type": "date",
                  "format": "dateOptionalTime"
               },
               "name": {
                  "type": "string"
               },
               "tweet": {
                  "type": "string"
               },
               "user_id": {
                  "type": "long"
               }
            }
         }
      }
   }
}

Elasticsearch中的資料可以大致分為兩種型別:

確切值確定的,正如它的名字一樣。比如一個date或使用者ID,確切值"Foo"和"foo"就並不相同。確切值2014和2014-09-15也不相同。
全文文字,文字化的資料,全文文字常常被稱為非結構化資料,匹配程度查詢,例如一封郵件

分析器:
當你查詢全文(full text)欄位,查詢將使用相同的分析器來分析查詢字串,以產生正確的詞列表。全文檢索需要分詞。
當你查詢一個確切值(exact value)欄位,查詢將不分析查詢字串,但是你可以自己指定。確切值查詢不需要分詞。

Elasticsearch支援以下簡單欄位型別:
型別             表示的資料型別
String             string
Whole number     byte, short, integer, long
Floating point     float, double
Boolean     boolean
Date             date
檢視對映:
GET /gb/_mapping/tweet

index值             解釋
analyzed     首先分析這個字串,然後索引。換言之,以全文形式索引此欄位。
not_analyzed     索引這個欄位,使之可以被搜尋,但是索引內容和指定值一樣。不分析此欄位。
no             不索引這個欄位。這個欄位不能為搜尋到。

string型別欄位預設值是analyzed。如果我們想對映欄位為確切值,我們需要設定它為not_analyzed:

{
    "tag": {
        "type":     "string",
        "index":    "not_analyzed"
    }
}



葉子子句(leaf clauses)(比如match子句)用以在將查詢字串與一個欄位(或多欄位)進行比較
複合子句(compound)用以合併其他的子句。例如,bool子句允許你合併其他的合法子句,must,must_not或者should,如果可能的話:

{
    "bool": {
        "must":     { "match": { "tweet": "elasticsearch" }},
        "must_not": { "match": { "name":  "mary" }},
        "should":   { "match": { "tweet": "full text" }}
    }
}

must :: 多個查詢條件的完全匹配,相當於 and。
must_not :: 多個查詢條件的相反匹配,相當於 not。
should :: 至少有一個查詢條件匹配, 相當於 or。

結構化查詢(Query DSL)查詢語句會詢問每個文件的欄位值與特定值的匹配程度如何
結構化過濾(Filter DSL)一條過濾語句會詢問每個文件的欄位值是否包含著特定值

最常用到的查詢過濾語句:
term主要用於精確匹配哪些值,比如數字,日期,布林值或 not_analyzed的字串(未經分析的文字資料型別)

terms 跟 term 有點類似,但 terms 允許指定多個匹配條件。

range過濾允許我們按照指定範圍查詢一批資料
範圍操作符包含:
gt :: 大於
gte:: 大於等於
lt :: 小於
lte:: 小於等於

exists 和 missing 過濾可以用於查詢文件中是否包含指定欄位或沒有某個欄位

validate API 可以驗證一條查詢語句是否合法。
GET /gb/tweet/_validate/query
{
   "query": {
      "tweet" : {
         "match" : "really powerful"
      }
   }
}

以上請求的返回值告訴我們這條語句是非法的:

{
  "valid" :         false,
  "_shards" : {
    "total" :       1,
    "successful" :  1,
    "failed" :      0
  }
}

理解查詢語句:使用 explain 引數可以返回一個帶有查詢語句的可閱讀描述
GET /_validate/query?explain
{
   "query": {
      "match" : {
         "tweet" : "really powerful"
      }
   }
}

explanation 會為每一個索引返回一段描述,因為每個索引會有不同的對映關係和分析器:

{
  "valid" :         true,
  "_shards" :       { ... },
  "explanations" : [ {
    "index" :       "us",
    "valid" :       true,
    "explanation" : "tweet:really tweet:powerful"
  }, {
    "index" :       "gb",
    "valid" :       true,
    "explanation" : "tweet:really tweet:power"
  } ]
}

【原創】原創文章,更多關注敬請關注

微信公眾號。