介紹
Elasticsearch 是一個分布式的免費開源搜索和分析引擎,適用於包括文本、數字、地理空間、結構化和非結構化數據等在內的所有類型的數據。
其特點是:
- 一個分布式的實時文檔存儲,每個字段 可以被索引與搜索
- 一個分布式實時分析搜索引擎
- 能勝任上百個服務節點的擴展,並支持 PB 級別的結構化或者非結構化數據
基本概念
1、Index(索引)
動詞:相當於MySQL的insert;
名詞:相當於MySQL的Database。
2、Type(類型)
在Index中,可以定義一個或多個類型。類似於MySQL中的Table,每一種類型的數據放在一起。
3、Document(文檔)
保存在某個索引(Index)下,某種類型(Type)的一個數據(Document),文檔是JSON格式的,Document就像是MySQL中的某個Table里面的內容。
4、倒排索引
在存儲數據時,ES會將整句拆分為單詞,以單詞來反向檢索整句。
docker安裝ES
初步檢索
1、_cat
GET/_cat/nodes //查看所有節點
GET/_cat/health //查看es健康狀況
GET/_cat/master //查看主節點
GET/_cat/indices //查看所有索引
2、索引一個文檔(保存)
//在customer索引下的external類型下保存1號數據為
PUT customer/external/1
{
"name":"John Doe"
}
PUT和POST都可以:
- POST新增。如果不指定id,會自動生成id。指定id就會修改這個數據,並新增版本號。
- PUT可以新增可以修改。PUT必須指定id,由於PUT需要指定id,我們一般用來做修改操作,不指定id會報錯。
3、查詢文檔
GET customer/external/1
//結果:
{
"_index" : "customer", //索引
"_type" : "external", //類型
"_id" : "1", //記錄id
"_version" : 1, //版本號
"_seq_no" : 0, //並發控制字段,每次更新就會+1,用來做樂觀鎖
"_primary_term" : 1, //同上,主分片重新分配,如重啟,就會變化
"found" : true,
"_source" : {
"name" : "John Doe"
}
}
//可以用_seq_no和_primary_term做並發時的樂觀鎖
//在更新時攜帶當前的這兩個值,后台更新時如發現這兩個值已經變化了(即更新過)則會更新失敗
//?if_seq_no=1&if_primary_term=1
4、更新文檔
//該方法會對比原來數據,如果數據與原來一樣,則什么都不做
POST customer/external/1/_update
{
"doc" : {
"name":"John Doew"
}
}
//或者 不帶update則不會檢查原數據,會一直更新
POST customer/external/1
{
"name":"John Doe2"
}
//或者
PUT customer/external/1
{
"name":"John Doe2"
}
//更新同時增加屬性 不帶update也可以
POST customer/external/1/_update
{
"doc":{"name":"Jane Doe","age":20}
}
5、刪除文檔&索引
//刪除文檔
DELETE customer/external/1
//刪除索引 不能直接刪除類型
DELETE customer
6、bulk批量API
POST customer/external/_bulk
{"index":{"_id":"1"}}
{"name":"John Doe"}
{"index":{"_id":"2"}}
{"name":"John Doe"}
//語法格式
{action:{metadata}}\n
{request body}\n
進階檢索
1.准備
為了測試更復雜的情況,需要將官方提供的測試數據用批量命令進行導入。
//命令是
POST bank/account/_bulk
//后跟上面的測試數據
2. 基本語法
//查詢語句的典型結構
{
QUERY_NAME:{
ARGUMENT:VALUE,
ARGUMENT:VALUE,
}
}
//例子
GET bank/_search
{
//查詢條件
"query": {
"match_all": {}
},
//排序方式
"sort": [
{
"account_number": "asc"
} ,
{
"balance": "desc"
}
],
//分頁
"from": 0,
"size": 20,
//顯示哪些信息
"_source": ["balance", "firstname"]
}
3. match
全文匹配,如果是數值類型會進行完全匹配,如果是字符串類型則會對檢索條件進行分詞匹配,返回的結果會按得分從高到低排列。
如果字符串類型的要匹配精確的值,可在字段后面加上.keyword
GET bank/_search
{
"query": {
"match": {
"balance": 16418
}
}
}
//查到了19條記錄
GET bank/_search
{
"query": {
"match": {
"address": "Mill lane"
}
}
}
4. math_phrase
短語匹配,將需要匹配的值當成一個整體單詞(不分詞)進行檢索。
//只能查到一條記錄
GET bank/_search
{
"query": {
"match_phrase": {
"address": "Mill lane"
}
}
}
5. multi_match
多字段匹配,即多個字段匹配檢索條件。
//address和city會分別與mill和movico進行匹配
GET bank/_search
{
"query": {
"multi_match": {
"query": "mill movico",
"fields": ["address","city"]
}
}
}
6. bool復合查詢
GET bank/_search
{
"query": {
"bool": {
//必須滿足
"must": [
{
"match": {
"gender": "M"
}
},
{
"match": {
"address": "mill"
}
}
],
//必須不是 相當於過濾器
"must_not": [
{
"match": {
"age": 28
}
}
],
//應該滿足 滿足了分數會相應提高,不滿足不會被過濾掉
"should": [
{
"match": {
"lastname": "Hines"
}
}
]
}
}
}
7. filter
//filter就是一個過濾器.能夠對查詢到的結果進行過濾,且不會貢獻相關性得分
GET bank/_search
{
"query": {
"bool": {
"filter": [
{
"range": {
"age": {
"gte": 10,
"lte": 20
}
}
}
]
}
}
}
8. term
和match一樣,匹配某個屬性的值。
建議:全文檢索字段用match,其他非text字段匹配用term
GET bank/_search
{
"query": {
"term": {
"balance": {
"value": 32838
}
}
}
}
//完全匹配,不能查到數據
GET bank/_search
{
"query": {
"match": {
"address.keyword": "798 Farragut"
}
}
}
//對比上面,短語匹配,能查到一條數據
GET bank/_search
{
"query": {
"match_phrase": {
"address": "798 Farragut"
}
}
}
聚合(aggregations)
聚合提供了從數據中分組和提取數據的能力。最簡單的聚合方法大致等於SQL GROUP BY和SQL聚合函數。在ES中,執行搜索會返回hits(命中結果),並且同時返回聚合結果,把一個響應中的所有hits分隔開的能力。
//搜索address中包含mill的所有人的年齡分布以及平均年齡
GET bank/_search
{
"query": {
"match": {
"address": "mill"
}
},
"aggs": {
"ageAgg": {
"terms": {
"field": "age",
"size": 10
}
},
"ageAvg":{
"avg": {
"field": "age"
}
}
}
}
//返回的聚合結果為
"aggregations" : {
"ageAgg" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : 38,
"doc_count" : 2
},
{
"key" : 28,
"doc_count" : 1
},
{
"key" : 32,
"doc_count" : 1
}
]
},
"ageAvg" : {
"value" : 34.0
}
}
//按照年齡聚合,並且請求這些年齡段的平均薪資
GET bank/_search
{
"query": {
"match_all": {}
},
"aggs": {
"ageAgg": {
"terms": {
"field": "age",
"size": 3
},
"aggs": {
"avgAgg": {
"avg": {
"field": "balance"
}
}
}
}
}
}
//返回的結果
"aggregations" : {
"ageAgg" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 820,
"buckets" : [
{
"key" : 31,
"doc_count" : 61,
"avgAgg" : {
"value" : 28312.918032786885
}
},
{
"key" : 39,
"doc_count" : 60,
"avgAgg" : {
"value" : 25269.583333333332
}
},
{
"key" : 26,
"doc_count" : 59,
"avgAgg" : {
"value" : 23194.813559322032
}
}
]
}
}
映射(Mapping)
映射是定義文檔及其包含的字段的存儲和索引方式的過程。
每個文檔都是字段的集合,每個字段都有自己的 數據類型。映射數據時,您將創建一個映射定義,其中包含與文檔相關的字段列表。映射定義還包括元數據字段,例如該
_source
字段,用於自定義如何處理文檔的關聯元數據。使用動態映射和顯式映射來定義數據。每種方法都會根據您在數據旅途中的位置提供不同的好處。例如,將字段顯式映射到您不想使用默認值的位置,或者獲得對創建哪些字段的更大控制權。然后,您可以允許Elasticsearch動態添加其他字段。
1. 創建一個索引並且指定映射
PUT /my-index-000001
{
"mappings": {
"properties": {
"age": { "type": "integer" },
"email": { "type": "keyword" },
"name": { "type": "text" }
}
}
}
2. 在索引中添加映射
PUT /my-index-000001/_mapping
{
"properties": {
"addr": { "type": "keyword" }
}
}
3. 更新映射
不能更新映射。
4. 數據遷移
//先創建出new_twitter的正確映射
//然后使用如下方式進行數據遷移
POST _reindex [固定寫法]
{
"source":{
"index": "twitter",
"type": "tweet" //如果有類型需加上
},
"dest":{
"index": "new_twitter"
}
}