1. 程式人生 > >【轉載】[Elasticsearch]ES入門

【轉載】[Elasticsearch]ES入門

簡單的 clas lba 檢索 hits 需要 字段 數據庫 host

傳送門:http://www.cnblogs.com/xing901022

ES即簡單又復雜,你可以快速的實現全文檢索,又需要了解復雜的REST API。本篇就通過一些簡單的搜索命令,幫助你理解ES的相關應用。雖然不能讓你理解ES的原理設計,但是可以幫助你理解ES,探尋更多的特性。

其他相關的內容參考:Elasticsearch官方文檔翻譯

樣例數據

為了更好的使用和理解ES,沒有點樣例數據還是不好模擬的。這裏提供了一份官網上的數據,accounts.json。如果需要的話,也可以去這個網址玩玩,它可以幫助你自定義寫隨機的JSON數據。

首先開啟你的ES,然後執行下面的命令,windows下需要自己安裝curl、也可以使用cygwin模擬curl命令:

curl -XPOST ‘localhost:9200/bank/account/_bulk?pretty‘ --data-binary  @accounts.json

註意:

1 需要在accounts.json所在的目錄運行curl命令。

2 localhost:9200是ES得訪問地址和端口

3 bank是索引的名稱

4 account是類型的名稱

5 索引和類型的名稱在文件中如果有定義,可以省略;如果沒有則必須要指定

6 _bulk是rest得命令,可以批量執行多個操作(操作是在json文件中定義的,原理可以參考之前的翻譯)

7 pretty是將返回的信息以可讀的JSON形式返回。

執行完上述的命令後,可以通過下面的命令查詢:

curl ‘localhost:9200/_cat/indices?v‘
health index pri rep docs.count docs.deleted store.size pri.store.size
yellow bank    5   1       1000            0    424.4kb        424.4kb

搜索API

ES提供了兩種搜索的方式:請求參數方式請求體方式

請求參數方式

curl ‘localhost:9200/bank/_search?q=*&pretty‘

其中bank是查詢的索引名稱,q後面跟著搜索的條件:q=*表示查詢所有的內容

請求體方式(推薦這種方式)

curl -XPOST ‘localhost:9200/bank/_search?pretty‘ -d ‘
{
  "query": { "match_all": {} }
}‘

這種方式會把查詢的內容放入body中,會造成一定的開銷,但是易於理解。在平時的練習中,推薦這種方式。

返回的內容

技術分享圖片
{
  "took" : 26,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 1000,
    "max_score" : 1.0,
    "hits" : [ {
      "_index" : "bank",
      "_type" : "account",
      "_id" : "1",
      "_score" : 1.0, "_source" : {"account_number":1,"balance":39225,"firstname":"Amber","lastname":"Duke","age":32,"gender":"M","address":"880 Holmes Lane","employer":"Pyrami","email":"[email protected]","city":"Brogan","state":"IL"}
    }, {
      "_index" : "bank",
      "_type" : "account",
      "_id" : "6",
      "_score" : 1.0, "_source" : {"account_number":6,"balance":5686,"firstname":"Hattie","lastname":"Bond","age":36,"gender":"M","address":"671 Bristol Street","employer":"Netagy","email":"[email protected]","city":"Dante","state":"TN"}
    }, {
      "_index" : "bank",
      "_type" : "account",
      "_id" : "13",
技術分享圖片

返回的內容大致可以如下講解:

took:是查詢花費的時間,毫秒單位

time_out:標識查詢是否超時

_shards:描述了查詢分片的信息,查詢了多少個分片、成功的分片數量、失敗的分片數量等

hits:搜索的結果,total是全部的滿足的文檔數目,hits是返回的實際數目(默認是10)

_score是文檔的分數信息,與排名相關度有關,參考各大搜索引擎的搜索結果,就容易理解。

由於ES是一次性返回所有的數據,因此理解返回的內容是很必要的。它不像傳統的SQL是先返回數據的一個子集,再通過數據庫端的遊標不斷的返回數據(由於對傳統的數據庫理解的不深,這裏有錯還望指正)。

查詢語言DSL

ES支持一種JSON格式的查詢,叫做DSL,domain specific language。這門語言剛開始比較難理解,因此通過幾個簡單的例子開始:

下面的命令,可以搜索全部的文檔:

{
  "query": { "match_all": {} }
}

query定義了查詢,match_all聲明了查詢的類型。還有其他的參數可以控制返回的結果:

curl -XPOST ‘localhost:9200/bank/_search?pretty‘ -d ‘
{
  "query": { "match_all": {} },
  "size": 1
}‘

上面的命令返回了所有文檔數據中的第一條文檔。如果size不指定,那麽默認返回10條。

下面的命令請求了第10-20的文檔。

技術分享圖片
curl -XPOST ‘localhost:9200/bank/_search?pretty‘ -d ‘
{
  "query": { "match_all": {} },
  "from": 10,
  "size": 10
}‘
技術分享圖片

下面的命令指定了文檔返回的排序方式:

curl -XPOST ‘localhost:9200/bank/_search?pretty‘ -d ‘
{
  "query": { "match_all": {} },
  "sort": { "balance": { "order": "desc" } }
}‘

執行搜索

上面了解了基本的搜索語句,下面就開始深入一些常用的DSL了。

之前的返回數據都是返回文檔的所有內容,這種對於網絡的開銷肯定是有影響的,下面的例子就指定了返回特定的字段:

curl -XPOST ‘localhost:9200/bank/_search?pretty‘ -d ‘
{
  "query": { "match_all": {} },
  "_source": ["account_number", "balance"]
}‘

再回到query,之前的查詢都是查詢所有的文檔,並不能稱之為搜索引擎。下面就通過match方式查詢特定字段的特定內容,比如查詢余額為20的賬戶信息:

curl -XPOST ‘localhost:9200/bank/_search?pretty‘ -d ‘
{
  "query": { "match": { "account_number": 20 } }
}‘

查詢地址為mill的信息:

curl -XPOST ‘localhost:9200/bank/_search?pretty‘ -d ‘
{
  "query": { "match": { "address": "mill" } }
}‘

查詢地址為mill或者lane的信息:

curl -XPOST ‘localhost:9200/bank/_search?pretty‘ -d ‘
{
  "query": { "match": { "address": "mill lane" } }
}‘

如果我們想要返回同時包含mill和lane的,可以通過match_phrase查詢:

curl -XPOST ‘localhost:9200/bank/_search?pretty‘ -d ‘
{
  "query": { "match_phrase": { "address": "mill lane" } }
}‘

ES提供了bool查詢,可以把很多小的查詢組成一個更為復雜的查詢,比如查詢同時包含mill和lane的文檔:

技術分享圖片
curl -XPOST ‘localhost:9200/bank/_search?pretty‘ -d ‘
{
  "query": {
    "bool": {
      "must": [
        { "match": { "address": "mill" } },
        { "match": { "address": "lane" } }
      ]
    }
  }
}‘
技術分享圖片

修改bool參數,可以改為查詢包含mill或者lane的文檔:

技術分享圖片
curl -XPOST ‘localhost:9200/bank/_search?pretty‘ -d ‘
{
  "query": {
    "bool": {
      "should": [
        { "match": { "address": "mill" } },
        { "match": { "address": "lane" } }
      ]
    }
  }
}‘
技術分享圖片

也可以改寫為must_not,排除包含mill和lane的文檔:

技術分享圖片
curl -XPOST ‘localhost:9200/bank/_search?pretty‘ -d ‘
{
  "query": {
    "bool": {
      "must_not": [
        { "match": { "address": "mill" } },
        { "match": { "address": "lane" } }
      ]
    }
  }
}‘
技術分享圖片

bool查詢可以同時使用must, should, must_not組成一個復雜的查詢:

技術分享圖片
curl -XPOST ‘localhost:9200/bank/_search?pretty‘ -d ‘
{
  "query": {
    "bool": {
      "must": [
        { "match": { "age": "40" } }
      ],
      "must_not": [
        { "match": { "state": "ID" } }
      ]
    }
  }
}‘
技術分享圖片

過濾查詢

之前說過score字段指定了文檔的分數,使用查詢會計算文檔的分數,最後通過分數確定哪些文檔更相關,返回哪些文檔。

有的時候我們可能對分數不感興趣,就可以使用filter進行過濾,它不會去計算分值,因此效率也就更高一些。

filter過濾可以嵌套在bool查詢內部使用,比如想要查詢在2000-3000範圍內的所有文檔,可以執行下面的命令:

技術分享圖片
curl -XPOST ‘localhost:9200/bank/_search?pretty‘ -d ‘
{
  "query": {
    "bool": {
      "must": { "match_all": {} },
      "filter": {
        "range": {
          "balance": {
            "gte": 20000,
            "lte": 30000
          }
        }
      }
    }
  }
}‘
技術分享圖片

ES除了上面介紹過的範圍查詢range、match_all、match、bool、filter還有很多其他的查詢方式,這裏就先不一一說明了。

聚合

聚合提供了用戶進行分組和數理統計的能力,可以把聚合理解成SQL中的GROUP BY和分組函數。在ES中,你可以在一次搜索查詢的時間內,即完成搜索操作也完成聚合操作,這樣就降低了多次使用REST API造成的網絡開銷。

下面就是通過terms聚合的簡單樣例:

技術分享圖片
curl -XPOST ‘localhost:9200/bank/_search?pretty‘ -d ‘
{
  "size": 0,
  "aggs": {
    "group_by_state": {
      "terms": {
        "field": "state"
      }
    }
  }
}‘
技術分享圖片

它類似於SQL中的下面的語句:

SELECT state, COUNT(*) FROM bank GROUP BY state ORDER BY COUNT(*) DESC

返回的數據:

技術分享圖片
"hits" : {
    "total" : 1000,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "group_by_state" : {
      "buckets" : [ {
        "key" : "al",
        "doc_count" : 21
      }, {
        "key" : "tx",
        "doc_count" : 17
      }, {
        "key" : "id",
        "doc_count" : 15
      }, {
        "key" : "ma",
        "doc_count" : 15
      }, {
        "key" : "md",
        "doc_count" : 15
      }, {
        "key" : "pa",
        "doc_count" : 15
      }, {
        "key" : "dc",
        "doc_count" : 14
      }, {
        "key" : "me",
        "doc_count" : 14
      }, {
        "key" : "mo",
        "doc_count" : 14
      }, {
        "key" : "nd",
        "doc_count" : 14
      } ]
    }
  }
}
技術分享圖片

由於size設置為0,它並沒有返回文檔的信息,只是返回了聚合的結果。

比如統計不同賬戶狀態下的平均余額:

技術分享圖片
curl -XPOST ‘localhost:9200/bank/_search?pretty‘ -d ‘
{
  "size": 0,
  "aggs": {
    "group_by_state": {
      "terms": {
        "field": "state"
      },
      "aggs": {
        "average_balance": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  }
}‘
技術分享圖片

聚合支持嵌套,舉個例子,先按範圍分組,在統計不同性別的賬戶余額:

技術分享圖片
curl -XPOST ‘localhost:9200/bank/_search?pretty‘ -d ‘
{
  "size": 0,
  "aggs": {
    "group_by_age": {
      "range": {
        "field": "age",
        "ranges": [
          {
            "from": 20,
            "to": 30
          },
          {
            "from": 30,
            "to": 40
          },
          {
            "from": 40,
            "to": 50
          }
        ]
      },
      "aggs": {
        "group_by_gender": {
          "terms": {
            "field": "gender"
          },
          "aggs": {
            "average_balance": {
              "avg": {
                "field": "balance"
              }
            }
          }
        }
      }
    }
  }
}‘
技術分享圖片

聚合可以實現很多復雜的功能,而且ES也提供了很多復雜的聚合,這裏作為引導篇,也不過多介紹了。

【轉載】[Elasticsearch]ES入門