ElasticSearch學習二-文檔與搜索

1. 文檔

在 Elasticsearch 中,每一個字段的全部數據都是默認被索引的。html

大多數實體和對象均可以被序列化爲包含鍵值對的JSON對象,JSON對象能表示字符串、數字、布爾值、甚至另外一個對象。以下所示:web

{
    "name":         "John Smith",
    "age":          42,
    "confirmed":    true,
    "join_date":    "2014-06-01",
    "home": {
        "lat":      51.5,
        "lon":      0.1
    },
    "accounts": [
        {
            "type": "facebook",
            "id":   "johnsmith"
        },
        {
            "type": "twitter",
            "id":   "johnsmith"
        }
    ]
}
複製代碼

文檔的定義:它是指最頂層或者根對象, 這個根對象被序列化成 JSON 並存儲到 Elasticsearch 中,指定了惟一 ID。數據庫

1.1 文檔的元數據

元數據 —— 有關文檔的信息,與文檔包含的數據相區分。json

有以下三個元數據:數組

  1. _index:文檔存放在哪網絡

    一個索引應該是因共同的特性被分組到一塊兒的文檔集合,如可能存儲全部的產品在索引 products 中。索引名必須小寫,不能如下劃線開頭,不能包含逗號。併發

  2. _type:文檔的類型elasticsearch

    Elasticsearch 公開了一個稱爲 types (類型)的特性,它容許您在索引中對數據進行邏輯分區。不一樣 types 的文檔可能有不一樣的字段,但最好可以很是類似。至關於在_index下繼續細分。ide

  3. _id:文檔的惟一標識post

    ID 是一個字符串, 當它和 _index 以及 _type 組合就能夠惟一肯定 Elasticsearch 中的一個文檔。

1.2 儲存文檔

如何肯定一個文檔的位置呢?就如上面所說的,三個元數據肯定一個文檔。如儲存一個文檔:

PUT /{index}/{type}/{id}
{
  "field": "value",
  ...
}
複製代碼

如何像數據庫自增主鍵那樣由ElasticSearch提供id呢,使用POST謂詞就能夠了。

POST /website/blog/
{
  "title": "My second blog entry",
  "text":  "Still trying this out...",
  "date":  "2014/01/01"
}
複製代碼

會自動生成一個基於 Base64 編碼且長度爲 20 個字符的 GUID 字符串

1.3 取回文檔

一樣的只須要把謂詞改成GET,同時提供三個元數據就能夠了:

GET /website/blog/123?pretty
複製代碼

加上pretty參數使得 JSON 響應體更加可讀。若是隻想返回文檔的一部分則在url上添加_source指定想要的字段就好了。

1.4 更新整個文檔

在 Elasticsearch 中文檔是不可改變的,不能修改它們,只能進行替換。至關於使用PUT再從新將整個文檔PUT一下,Elasticsearch將舊文檔標記爲已刪除,並增長一個全新的文檔。

(建立和刪除文檔略)

1.5 部分更新文檔

使用 update API能夠部分更新文檔,例如在某個請求時對計數器進行累加。對象被合併到一塊兒,覆蓋現有的字段,增長新的字段。如:

POST /website/blog/1/_update
{
   "doc" : {
      "tags" : [ "testing" ],
      "views": 0
   }
}
複製代碼

在文檔中增長了tags和views字段。

也可使用腳本和參數更新:

POST /website/blog/1/_update
{
   "script" : "ctx._source.tags+=new_tag",
   "params" : {
      "new_tag" : "search"
   }
}
複製代碼

爲了不數據丟失, update API 在檢索步驟時檢索獲得文檔當前的 _version 號,並傳遞版本號到重建索引步驟的 index 請求。 若是另外一個進程修改了處於檢索和從新索引步驟之間的文檔,那麼 _version 號將不匹配,更新請求將會失敗。

還能夠在url後加上retry_on_conflict=5參數,表示失敗以前重試5次。

1.6 樂觀併發控制

ElasticSearch使用樂觀併發控制,每一個文檔都有一個版本號_version,當文檔被修改時版本號遞增。 Elasticsearch 使用這個 _version 號來確保變動以正確順序獲得執行。咱們經過指定想要修改文檔的 version 號來達到這個目的,若是該版本不是當前版本號,咱們的請求將會失敗(也就是一次Compare And Set)。

1.7 批量取回多個文檔

使用mget API來取回多個文檔能夠減小網絡流量,參數在請求體裏的docs數組中提供:

GET /_mget
{
   "docs" : [
      {
         "_index" : "website",
         "_type" :  "blog",
         "_id" :    2
      },
      {
         "_index" : "website",
         "_type" :  "pageviews",
         "_id" :    1,
         "_source": "views"
      }
   ]
}
複製代碼

還有其餘的批量查詢方法能夠查看官方文檔

返回文檔順序和請求的一致。

1.8 批量操做

很簡單一看就懂,使用bulk API,主要就是語法的問題,不太好掌握。

POST /_bulk
{ "delete": { "_index": "website", "_type": "blog", "_id": "123" }} 
{ "create": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "title":    "My first blog post" }
{ "index":  { "_index": "website", "_type": "blog" }}
{ "title":    "My second blog post" }
{ "update": { "_index": "website", "_type": "blog", "_id": "123", "_retry_on_conflict" : 3} }
{ "doc" : {"title" : "My updated blog post"} } 
複製代碼

2. 搜索

2.1 空搜索

什麼條件也不附加的空搜索,搜索ElasticSearch中的全部文檔:

GET /_search
複製代碼

返回全部查詢結果的前十個文檔而不是隻是返回id。

2.2 指定index,type搜索

前面的空搜索是搜索全部文檔,若是要想指定元數據搜索怎麼辦呢?很好辦,在url中指明便可:

/gb/_search

gb 索引中搜索全部的類型

/gb,us/_search

gbus 索引中搜索全部的文檔

/g*,u*/_search

在任何以 g 或者 u 開頭的索引中搜索全部的類型

/gb/user/_search

gb 索引中搜索 user 類型

/gb,us/user,tweet/_search

gbus 索引中搜索 usertweet 類型

/_all/user,tweet/_search

在全部的索引中搜索 usertweet 類型

2.3 分頁

和傳統的數據庫同樣,ElasticSearch也有分頁的功能,使用from 和 size 參數:

size

顯示應該返回的結果數量,默認是 10

from

顯示應該跳過的初始結果數量,默認是 0

GET /_search?size=5&from=10
複製代碼

2.4 輕量級搜索

以前咱們看到的搜索都是有個JSON請求體,可是還有一種更簡便的輕量級搜索方式.

  1. 搜索全部包含關鍵字的文檔:

    GET /_search?q=mary
    複製代碼
  2. 搜索包含關鍵字的全部文檔:

    GET /_search?q=mary
    複製代碼
  3. 指定匹配多個關鍵字的文檔:

    GET /_search?q=+name:john +tweet:mary
    複製代碼

    + 前綴表示必須與查詢條件匹配。相似地, - 前綴表示必定不與查詢條件匹配。

    注意+、-、:都要使用URL編碼,實際上上面的查詢語句應該是:

    GET /_search?q=%2Bname%3Ajohn+%2Btweet%3Amary
    複製代碼

那麼ElasticSearch如何從JSON的不一樣字段搜索關鍵字呢?原來ElasticSearch在儲存一個文檔上,會將該JSON全部字段提取出來拼接成一個字符串,而後增長一個_all字段,將該字符串添加到all字段上。

3. 請求體查詢

請求體查詢就像是一個帶請求體的GET請求:

GET /_search
{
  "from": 30,
  "size": 10
}
複製代碼

3.1 查詢表達式

Elasticsearch 使用查詢表達式能夠以簡單的 JSON 接口來編寫查詢語句。只須要將語句傳遞給query參數就能夠了。如查詢 tweet 字段中包含 elasticsearch 的 tweet:

GET /_search
{
    "query": {
        "match": {
            "tweet": "elasticsearch"
        }
    }
}
複製代碼

當你有多個查詢條件是能夠合併查詢語句:

{
    "bool": {
        "must":     { "match": { "tweet": "elasticsearch" }},
        "must_not": { "match": { "name":  "mary" }},
        "should":   { "match": { "tweet": "full text" }},
        "filter":   { "range": { "age" : { "gt" : 30 }} }
    }
}
複製代碼

3.2 重要的查詢

  1. 默認查詢match_all匹配全部文檔:
{ "match_all": {}}
複製代碼
  1. 標準查詢match,可用於全文搜索和精確查詢:
{ "match": { "age":    26           }}
{ "match": { "date":   "2014-09-01" }}
{ "match": { "public": true         }}
{ "match": { "tag":    "full_text"  }}
複製代碼
  1. mulit_match查詢,能夠在多個字段上執行相同的 match 查詢:
{
    "multi_match": {
        "query":    "full text search",
        "fields":   [ "title", "body" ]
    }
}
複製代碼
  1. range查詢,有gt,gte,lt,lte字段:
{
    "range": {
        "age": {
            "gte":  20,
            "lt":   30
        }
    }
}
複製代碼
  1. term查詢用於精確匹配,不對查詢字符串作分析處理
{ "term": { "age":    26           }}
{ "term": { "date":   "2014-09-01" }}
{ "term": { "public": true         }}
{ "term": { "tag":    "full_text"  }}
複製代碼

3.3 組合多查詢

若是想在多個字段上查詢多種多樣的文本怎麼辦呢?可使用bool 查詢來實現你的需求。bool 查詢接收如下參數:

must

文檔 必須 匹配這些條件才能被包含進來。

must_not

文檔 必須不 匹配這些條件才能被包含進來。

should

若是知足這些語句中的任意語句,將增長 _score ,不然,無任何影響。它們主要用於修正每一個文檔的相關性得分。

filter

必須 匹配,但它以不評分、過濾模式來進行。這些語句對評分沒有貢獻,只是根據過濾標準來排除或包含文檔。

以下面這個查詢的意思是必須知足title 字段匹配 how to make millions而且不被標識爲 spam 的文檔。若是是starred且在2014年後的郵件會有更高的排名:

"bool": {
        "must":     { "match": { "title": "how to make millions" }},
        "must_not": { "match": { "tag":   "spam" }},
        "should": [
            { "match": { "tag": "starred" }},
            { "range": { "date": { "gte": "2014-01-01" }}}
        ]
    }
複製代碼

每個子查詢都獨自地計算文檔的相關性得分。一旦他們的得分被計算出來, bool 查詢就將這些得分進行合併而且返回一個表明整個布爾操做的得分。

bool查詢默認是評分的,將 bool 查詢包裹在 filter 語句中,就能夠在過濾標準中增長布爾邏輯。

相關文章
相關標籤/搜索