ElasticSearch入門介紹一

ElasticSearchhtml

 

關於es的幾個概念:node

集羣:多個運行es節點能夠組成一個集羣,它們擁有相同的cluster.name。數據庫

節點:運行es的實例json

索引:至關於數據庫database,一個集羣能夠有多個索引(數據庫)。 索引其實是指向一個或者多個物理分片的邏輯命名空間 數組

分片:索引的子集,一個索引能夠被切成多個分片。分片又分爲主分片和副分片,副分片是主分片的副本。一個分片是一個底層的工做單元 ,它僅保存了所有數據中的一部分。Elasticsearch 是利用分片將數據分發到集羣內各處的。分片是數據的容器,文檔保存在分片內,分片又被分配到集羣內的各個節點裏。 當你的集羣規模擴大或者縮小時, Elasticsearch 會自動的在各節點中遷移分片,使得數據仍然均勻分佈在集羣裏。併發

副本分片:一個副本分片只是一個主分片的拷貝。 副本分片做爲硬件故障時保護數據不丟失的冗餘備份,併爲搜索和返回文檔等讀操做提供服務。副本分片數量能夠隨時更改。curl

類型:至關於數據庫中的(表)table,一個索引(數據庫)包含多個類型(表)。異步

文檔:至關於表中的行(row)。jvm

字段:至關於表中的列(cloum)。elasticsearch

分配:將分片分配給某個節點。

 

在es中,每一個索引的主分片默認爲5個,每一個主分片的副本默認爲1個。

 

1、安裝運行elasticsearch:

官網下載安裝包:https://www.elastic.co/cn/downloads。其中5.5版本的須要jdk1.8的支持。

配置文件的更改,參考:http://www.cnblogs.com/ahaii/p/7279930.html

運行es:

elasticsearch/bin/elasticsearch -d

-d 參數表示以守候進程方式在後臺運行。

查看是否運行成功:

curl http://localhost:9200/?pretty

{
  "name" : "node-164",
  "cluster_name" : "elk-cluster",
  "cluster_uuid" : "QLhDVsXUR8yHrD8ts3JZBA",
  "version" : {
    "number" : "5.5.1",
    "build_hash" : "19c13d0",
    "build_date" : "2017-07-18T20:44:24.823Z",
    "build_snapshot" : false,
    "lucene_version" : "6.6.0"
  },
  "tagline" : "You Know, for Search"
}

?pretty參數使得結果以json方式顯示。

 

2、利用es的RESTful API進行交互:

ElasticSearch提供RESTful API,經常使用格式爲:

curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'

其中:

-X<VBER>:能夠指定curl發起是的請求方式,如GET、PUT、POST、DELETE、HEAD

<PATH>:API路徑,如_cluster/stats、_nodes/stats/jvm

<QUERY_STRING>:查詢字符串參數,如?pretty參數將以json格式顯示查詢結果

<BODY>:json格式的請求體

例如如下統計文檔總數的請求格式:

curl -XGET 'http://localhost:9200/_count?pretty' -d '
{
    "query": {
        "match_all": {}
    }
}
'

 

一、建立文檔:

curl -XPUT http://localhost:9200/索引(數據庫)/類型(表)/id -d '{信息體}'
curl -XPUT http://localhost:9200/<index>/<type>/ID -d '{message}'

若是不指定id,es也支持隨機生成一個id,可是,請求方法須要用POST:

curl -XPOST http://localhost:9200/<index>/<type>

自動生成的 ID 是 URL-safe、 基於 Base64 編碼且長度爲20個字符的 GUID 字符串。 這些 GUID 字符串由可修改的 FlakeID 模式生成,這種模式容許多個節點並行生成惟一 ID ,且互相之間的衝突機率幾乎爲零。

{
   "_index":    "people",
   "_type":     "man",
   "_id":       "AVFgSgVHUP18jI2wRx0w",
   "_version":  1,
   "created":   true
}

 

二、查詢(檢索)文檔:

根據某ID檢索:

curl -XGET http://localhost:9200/<index>/<type>/ID

該請求默認獲取多有文檔數據,且得到的數據放存在"_source"字段內。

只請求文檔中一部分:

如,只須要id爲5的文檔中的name字段和job字段的值,則須要使用"?_source"字段:

curl -XGET http://localhost:9200/<index>/<type>/5?_source=name,job

所以,若是隻須要文檔中的數據,而不須要其餘元數據(如索引,id,和類型),則可使用"_source":

curl -XGET http://localhost:9200/<index>/<type>/id/_source

檢查一個文檔是否存在:

curl -XHEAD http://loclhost:9200/<index>/<type>/id

這裏使用的是HEAD請求方法,返回http狀態碼。若文檔存在,則返回200。若不存在, 則返回404。

檢索全部文檔:

curl -XGET http://localhost:9200/<index>/<type>/_search

根據字符串檢索:

curl -XGET http://localhost:9200/<index>/<type>/_search?q=name:ahaii

使用查詢表達式檢索:

curl -XGET http://localhost:9200/<index>/<type>/_search? -d '
{
    "query" : {
        "match" : {
            "name" : "ahaii"
        }
    }
}'

使用過濾器檢索:

curl -XGET http://localhost:9200/<index>/type/_search -d'
{
    "query" : {
        "bool": {
            "must": {
                "match" : {
                    "name" : "smith" 
                }
            },
            "filter": {
                "range" : {
                    "age" : { "gt" : 20 } 
                }
            }
        }
    }
}'

注意,這裏使用了filter過濾器,除了查詢name是ahaii的外,還要匹配年齡大於20。

全文檢索:

curl -XGET http://localhost:9200/<index>/<type>/_search -d '
{
    "query" : {
        "match" : {
            "about" : "like coding"
        }
    }
}'

檢索全部包含"like coding"字段的文檔。

若是有多個文檔包含該字段,則都會被返回。可是,es在返回結果中會添加一個「_score」字段。該字段是搜索結果的相關性得分。

相關性得分:

Elasticsearch 默認按照相關性得分對搜索結果進行排序,即每一個文檔跟查詢的匹配程度。徹底匹配查詢條件的其相關性得分最高,也就排在搜索結果的第一個。其餘包含查詢條件某個字段的相關性得分就會較低,排在搜索結果的後面。

短語檢索:

curl -XGET http://localhost:9200/<index>/<type>/_search
{
    "query" : {
        "match_phrase" : {
            "about" : "like coding"
        }
    }
}

這裏使用的是"match_phrase",匹配結果裏必須包含"like coding",且兩個單詞連在一塊兒。

 高亮檢索:

curl -XGET http://locahost:9200/<index>/<type>/_search -d '
{
    "query" : {
        "match_phrase" : {
            "about" : "like coding"
        }
    },
    "highlight": {
        "fields" : {
            "about" : {}
        }
    }
}'

這裏多了一個"highlight"部分,該部分包括了"about"屬性匹配到的字段,而且以 HTML 標籤 <em></em> 封裝,以變化顏色。

 

三、更新文檔:

在es中文檔是不可改變的,即不能修改它們。當須要更新數據時,能夠進行替換。

如如今id爲5的文檔數據以下:

curl -XGET http://localhost:9200/people/man/5

{
  "_index": "people",
  "_type": "man",
  "_id": "5",
  "_version": 1,
  "found": true,
  "_source": {
    "name": "ming",
    "age": 23,
    "job": "coding"
  }
}

如今,須要更新"age"字段的值,操做及結果以下:

curl -XPUT http://localhost:9200/people/man/5 -d '
{
  "name":"ming",
  "age":29,
  "job":"coding"
}
'

#更新後結果以下:
{
  "_index": "people",
  "_type": "man",
  "_id": "5",
  "_version": 2,
  "result": "updated",
  "_shards": {
    "total": 2,
    "successful": 2,
    "failed": 0
  },
  "created": false
}

返回的結果中,"_version"字段由原來的1變成了2,"result"爲"updated",且"created" 字段爲"false"。

在內部,Elasticsearch 已將舊文檔標記爲已刪除,並增長一個全新的文檔。 儘管你不能再對舊版本的文檔進行訪問,但它並不會當即消失。當繼續索引更多的數據,Elasticsearch 會在後臺清理這些已刪除文檔。

 

從以上執行更新文檔的操做中得出一個問題,在建立文檔時,若是該文檔已經存在,則會被覆蓋。這結果可能不是咱們想要的,那怎麼辦?

前面介紹過,在建立文檔時,可使用POST方法在建立文檔時生成一個隨機的ID,這樣可確保文檔不會重複(被覆蓋)。可是若是我想本身指定ID呢?

因爲es經過"_index"、"_type" 和"_id"三個字段來肯定一個惟一文檔,所以咱們在建立文檔時,必需要告訴es,只有這三個字段都不相同時才能建立新文檔。這裏有兩種方法:

3.一、使用"?op_type=create"參數:

建立一個已經的文檔:

curl -XPUT /people/man/5?op_type=create -d'
{
  "name":"daka",
  "age":25,
  "job":"teacher"
}'



#返回結果:

 {
  "error": {
    "root_cause": [
      {
        "type": "version_conflict_engine_exception",
        "reason": "[man][5]: version conflict, document already exists (current version [2])",
        "index_uuid": "_Xe9jJTdS6yKbGRBvet2qg",
        "shard": "1",
        "index": "people"
      }
    ],
    "type": "version_conflict_engine_exception",
    "reason": "[man][5]: version conflict, document already exists (current version [2])",
    "index_uuid": "_Xe9jJTdS6yKbGRBvet2qg",
    "shard": "1",
    "index": "people"
  },
  "status": 409
}

因爲"/people/man/5"文檔已存在,再建立時,會提示409。

3.二、在url中使用"create"參數:

一樣建立一個"/people/man/5"文檔,一樣返回409:

{
  "error": {
    "root_cause": [
      {
        "type": "version_conflict_engine_exception",
        "reason": "[man][5]: version conflict, document already exists (current version [2])",
        "index_uuid": "_Xe9jJTdS6yKbGRBvet2qg",
        "shard": "1",
        "index": "people"
      }
    ],
    "type": "version_conflict_engine_exception",
    "reason": "[man][5]: version conflict, document already exists (current version [2])",
    "index_uuid": "_Xe9jJTdS6yKbGRBvet2qg",
    "shard": "1",
    "index": "people"
  },
  "status": 409
}

這樣,就避免了舊文檔被覆蓋的狀況。

 

四、刪除文檔:

curl -XDELETE http://localhost:9200/<index>/<type>/id

這裏使用的是DELETE方法,成功刪除後,返回如下結果:

{
  "found": true,
  "_index": "people",
  "_type": "man",
  "_id": "5",
  "_version": 2,
  "result": "deleted",
  "_shards": {
    "total": 2,
    "successful": 2,
    "failed": 0
  }
}

注意,返回結果中的"_version"字段的值會增長,不管是否刪除成功,該字段的值都會增長,這是 Elasticsearch 內部記錄本的一部分,用來確保這些改變在跨多節點時以正確的順序執行。

刪除文檔不會當即將文檔從磁盤中刪除,只是將文檔標記爲已刪除狀態。隨着你不斷的索引更多的數據,Elasticsearch 將會在後臺清理標記爲已刪除的文檔。

 

五、更新文檔:

咱們知道,es中文檔不能被直接修改,只能被替換。可使用update參數對文檔進行更新的操做。 update API 簡單使用與以前描述相同的 檢索-修改-重建索引 的處理過程。

update 請求最簡單的一種形式是接收文檔的一部分做爲 doc 的參數, 它只是與現有的文檔進行合併。對象被合併到一塊兒,覆蓋現有的字段,增長新的字段。

curl -XPOST http://localhost:9200/people/man/5/_update
{
  "doc": {
    "tel":"122334",
    "like":"football"
  }
}
 

更新id爲5的文檔,添加"tel"和"like"兩個字段。更新後的文檔爲:

{
  "_index": "people",
  "_type": "man",
  "_id": "5",
  "_version": 4,
  "found": true,
  "_source": {
    "name": "ming",
    "age": 33,
    "job": "coding",
    "like": "football",
    "tel": "122334"
  }
}

 

六、檢索多個文檔:

須要從 Elasticsearch 檢索不少文檔,那麼使用 multi-get 或者 mget API 來將這些檢索請求放在一個請求中,將比逐個文檔請求更快地檢索到所有文檔。

mget API 要求有一個 docs 數組做爲參數,每一個元素包含須要檢索文檔的元數據, 包括 _index 、 _type 和 _id 。若是你想檢索一個或者多個特定的字段,那麼你能夠經過 _source 參數來指定這些字段的名字。一樣,查詢到的結果也包含在_source字段中:

curl  -XGET http://localhost:9200/_mget -d '
{
   "docs" : [
      {
         "_index" : "people",
         "_type" :  "man",
         "_id" :    1
      },
      {
         "_index" : "people",
         "_type" :  "man",
         "_id" :    2,
         "_source": "name"
      }
   ]
}'

docs參數中包含兩個查詢條件,第一個查詢符合這三個條件的整個文檔的數據,第二個查詢查詢符合條件的文檔的"name"字段的值。查詢結果以下:

{
  "docs": [
    {
      "_index": "people",
      "_type": "man",
      "_id": "1",
      "_version": 1,
      "found": true,
      "_source": {
        "name": "ahaii",
        "age": 27,
        "job": "coding"
      }
    },
    {
      "_index": "people",
      "_type": "man",
      "_id": "2",
      "_version": 1,
      "found": true,
      "_source": {
        "name": "fukk"
      }
    }
  ]
}

 

若是要檢索的文檔在同一個index和type下,只須要傳一個 ids 數組,而不是整個 docs 數組:

curl -XGET http://localhost:9200/people/man/_mget -d'
{
  "ids":[3,5]
}'

查詢到的結果爲:

{
  "docs": [
    {
      "_index": "people",
      "_type": "man",
      "_id": "3",
      "_version": 1,
      "found": true,
      "_source": {
        "name": "tim",
        "age": 32,
        "job": "stu"
      }
    },
    {
      "_index": "people",
      "_type": "man",
      "_id": "5",
      "_version": 4,
      "found": true,
      "_source": {
        "name": "ming",
        "age": 33,
        "job": "coding",
        "like": "football",
        "tel": "122334"
      }
    }
  ]
}

在檢索多個文檔時,若是其中某些文檔不存在,則不會影響其餘文檔的檢索。不存在的文檔會返回false。

 

 

聚合檢索:

該部分在之後詳細介紹。

 

3、ElasticSearch中的避免衝突:  

 

一、經過內部version參數避免衝突

Elasticsearch 是分佈式的。當文檔建立、更新或刪除時, 新版本的文檔必須複製到集羣中的其餘節點。Elasticsearch 也是異步和併發的,這意味着這些複製請求被並行發送,而且到達目的地時也許 順序是亂的 。 Elasticsearch 須要一種方法確保文檔的舊版本不會覆蓋新的版本。

當咱們以前討論 index , GET 和 delete 請求時,咱們指出每一個文檔都有一個 _version (版本)號,當文檔被修改時版本號遞增。 Elasticsearch 使用這個 _version 號來確保變動以正確順序獲得執行。若是舊版本的文檔在新版本以後到達,它能夠被簡單的忽略。

咱們能夠利用 _version 號來確保 應用中相互衝突的變動不會致使數據丟失。咱們經過指定想要修改文檔的 version 號來達到這個目的。 若是該版本不是當前版本號,咱們的請求將會失敗。

按照_version的值對文檔進行修改:

curl -XPUT http://localhost:9200/<index>/<type>/5?version=2 -d'
{
  "name":"ming",
  "age":33,
  "job":"coding"
}'

即,只有當前_version的值爲2時,纔會執行該操做。若是該不存在,則返回409。

ElasticSearch中,每次更新和刪除,文檔的_version字段都會加1。

二、經過version_type=external字段添加外部版本控制

外部版本號的處理方式和咱們以前討論的內部版本號的處理方式有些不一樣, Elasticsearch 不是檢查當前 _version 和請求中指定的版本號是否相同, 而是檢查當前 _version 是否 小於 指定的版本號。 若是請求成功,外部的版本號做爲文檔的新 _version 進行存儲。

建立文檔時設置外部版本號:

curl -XPUT http://localhost:9200/people/man/30?version=3&version_type=external -d '

{
  "name":"tomi",
  "age":42,
  "job":"master"
}'

#返回結果:
 { "_index": "people", "_type": "man", "_id": "30", "_version": 3, "result": "created", "_shards": { "total": 2, "successful": 2, "failed": 0 }, "created": true }

能夠看到,當前版本是3。如今更新這個文檔,指定外部版本爲5:

curl -XPUT http://localhost:9200/people/man/30?version=5&version_type=external -d '
{
  "name":"tomi",
  "age":19,
  "job":"master"
}
'

#返回結果:

{
  "_index": "people",
  "_type": "man",
  "_id": "30",
  "_version": 5,
  "result": "updated",
  "_shards": {
    "total": 2,
    "successful": 2,
    "failed": 0
  },
  "created": false
}

從返回結果看到,version被設置成了10。若再次請求,會返回409。

相關文章
相關標籤/搜索