Elasticsearch使用詳解


1.1 elasticsearch是什么?

  • 簡稱ES,是一個開源的高擴展的分布式全文搜索引擎,它可以近乎實時的存儲、檢索數據;本身擴展性很好,可以擴展到上百台服務器,處理PB級別的數據,es使用Java開發並使用lucene作為其核心來實現所有索引和搜索的功能,但是它的目的是通過簡單的RestFul API來隱藏Lucene的復雜性,從而讓全文檢索變得簡單

1.2 soar和es比較

  • 當單純的對已有數據進行搜索時,soar更快
  • 當實時建立索引時,soar會產生IO阻塞,查詢性能較差,es具有明顯的優勢
  • 隨着數據量的增加,soar會變得越來越慢,而es沒有明顯的變化

1.3 es VS soar總結

  1. es基本開箱即用(解壓即可),而soar安裝稍微復雜一點點
  2. soar利用zookeeper進行分布式管理,而es自身帶有分布式協調管理功能
  3. soar支持更多格式的數據,如JSON、XML、csv,而es僅支持json格式
  4. soar官方提供的功能多,而es本身更注重於核心功能,高級功能多有第三方插件提供,例如圖形化界面需要kibana友好支撐
  5. soar查詢快,但更新索引時慢(即插入刪除慢),用於電商等查詢多的應用
  6. es建立索引快,即實時查詢快,多用於搜索

第二章 ES安裝

2.1 解壓即安裝

#把安裝包直接上傳到電腦,直接解壓即可
[es@ceshi opt]$ ll
total 16
drwxr-xr-x 10 es   es   4096 Aug 30 14:09 es
drwxr-xr-x  8 root root 4096 Apr  8 03:26 jdk1.8.0_291
drwxr-xr-x 13 root root 4096 Aug 30 11:12 kibana-7.8.0-linux-x86_64
drwxr-xr-x  2 root root 4096 Aug 30 11:12 src

2.2 熟悉目錄

bin        啟動文件
config     配置文件
   elasticsearch.yml  es默認配置文件
   log4j2.properties  日志配置文件
   jvm.options        虛擬機相關配置
lib       相關jar包
logs      日志
modules   功能模塊
plugins   插件

2.3 啟動es

#在后台啟動
[es@ceshi bin]$ ./elasticsearch  -d
#es啟動默認使用普通用戶,注意目錄權限問題

2.4 訪問測試

#es默認使用兩個端口,9200為外部訪問端口,9300是集群內部通信端口
{
  "name" : "XIAOYAO",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "-J88UDSLSVqC1hxClaRG1w",
  "version" : {
    "number" : "7.8.0",
    "build_flavor" : "default",
    "build_type" : "zip",
    "build_hash" : "757314695644ea9a1dc2fecd26d1a43856725e65",
    "build_date" : "2020-06-14T19:35:50.234439Z",
    "build_snapshot" : false,
    "lucene_version" : "8.5.1",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

2.5 安裝es-head

#上傳安裝包到服務器,解壓
[root@ceshi src]# ls
elasticsearch-7.8.0-linux-x86_64.tar.gz  elasticsearch-head-master.zip  kibana-7.8.0-linux-x86_64.tar.gz
elasticsearch-analysis-ik-7.8.0.zip      jdk-8u291-linux-x64.tar.gz
[root@ceshi src]# unzip  elasticsearch-head-master.zip -d  /opt/

#進入到安裝目錄,執行命令,需要提前安裝npm命令
[root@ceshi elasticsearch-head]# npm  install
#運行es-head,在后台運行
[root@ceshi elasticsearch-head]# nohup npm  run  start  &
#訪問端口9100

2.6 解決跨域問題

#此時通過es-head直接連接es,會無法連接,需要解決下跨域問題;編輯es配置文件,在后面添加參數
http.cors.enabled: true 
http.cors.allow-origin: "*"

2.7 訪問測試

#重啟es,重新訪問9100端口

2.8 安裝kibana

  • kibana是一個針對elasticsearch的開源分析及可視化平台,用來搜索、查看交互存儲在Elasticsearch索引中的數據,使用kibana可以通過圖標進行高級數據分析及展示。

    #上傳軟件包並解壓
    [root@ceshi kibana]# cd  /opt/
    [root@ceshi opt]# ll
    total 20
    drwxr-xr-x  8 root root 4096 Aug 30 14:40 elasticsearch-head
    drwxr-xr-x 10 es   es   4096 Aug 30 14:09 es
    drwxr-xr-x  8 root root 4096 Apr  8 03:26 jdk1.8.0_291
    drwxr-xr-x 13 root root 4096 Aug 30 14:44 kibana
    drwxr-xr-x  2 root root 4096 Aug 30 11:12 src
    
    
    #修改配置文件
    [root@ceshi config]# vi  kibana.yml 
    server.host: "172.19.70.210"
    elasticsearch.hosts: ["http://172.19.70.210:9200"]
    i18n.locale: "zh-CN"
    
    #啟動服務,使用普通帳戶啟動
    [es@ceshi es]$ cd  ../kibana/bin/
    [es@ceshi bin]$ ./kibana  
    

第三章 初步查詢

3.1 _cat

  • 查看所有節點

    GET /_cat/nodes
    
  • 查看es健康狀況

    GET /_cat/health
    
  • 查看主節點

    GET /_cat/master
    
  • 查看所有索引

    GET /_cat/indices
    

3.2 索引一個文檔

#保存一個數據,保存在哪個索引的哪個類型下,指定用哪一個唯一標識
#在xiaoyao索引下的test類型的保存1號數據為:
PUT  xiaoyao/test/1
{
  "name":"xiaoyao"
}
#輸出信息:
{
  "_index" : "xiaoyao", #在哪個索引
  "_type" : "test",     #在哪個類型
  "_id" : "1",          #文檔id
  "_version" : 2,       #版本號
  "result" : "updated", #狀態
  "_shards" : {         #集群分片信息
    "total" : 2,        
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 1,       
  "_primary_term" : 1 
}
#PUT和POST都可以,PUT可以新增,可以修改,PUT必須指定id,由於指定id的原因,所以我們一般做修改操作,不指定id會報錯;
#POST新增,如果不指定id,會自動生成id,指定id會修改這個數據,並新增版本號

3.3 查詢文檔

GET xiaoyao/test/1
{
  "_index" : "xiaoyao", #在哪個索引
  "_type" : "test",     #在哪個類型
  "_id" : "1",          #文檔id
  "_version" : 2,       #版本號
  "_seq_no" : 1,        #並發控制手段,每次更新都會加1,用來做樂觀鎖 
  "_primary_term" : 1,  #同上,主分片重新分配。如重啟就會變化,需要結合使用
  "found" : true,
  "_source" : {         #真正的內容
    "name" : "xiaoyao"
  }
}
###測試樂觀鎖,打開兩個窗口指定seq_no,第一條數據新增后,seq_no會自增,另外一個會報錯409
PUT xiaoyao/test/1?if_seq_no=1&if_primary_term=1

3.4 更新文檔

#PUT和POST都可以更新文檔,PUT更多的是對原文檔覆蓋,常用POST請求加上_update可以對某一個字段進行更新
POST xiaoyao/test/1/_update
{
  "doc": {
    "name":"xiaoyao"
  }
}
#POST操作帶_updata會對比源文件 ,如果相同不會有任何操作,文檔version不增加,需要帶上“doc”參數
#POST不帶_updata和PUT請求效果一樣,會把源數據覆蓋。

3.5 刪除文檔&索引

#es可以對文檔和索引進行刪除操作,無法刪除類型
#刪除文檔
DELETE xiaoyao/test/1
#刪除索引
DELETE xiaoyao

3.6 bulk批量API

#只能使用post請求
POST  /xiaoyao/test/_bulk
{"index": {"_id":"1"}}
{"name": "xiaoyao"}
{"index": {"_id":"2"}}
{"name": "feng"}

#語法格式
{"action":{metadata}}
{request body}
{"action":{metadata}}
{request body}

#復雜實例
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"}}
#bulk API以此按順序執行所有的action,如果一個單個的動作因任何原因而失敗,它將繼續處理它后面剩余的工作,當bulk API返回時,它將提供每個動作的狀態(與發送的順序相同),所以您可以檢查是否一個指定的動作是不是失敗了

3.7 樣本測試數據

#准備es樣本數據
#下載鏈接
https://gitee.com/runewbie/learning/raw/master/ElasticSearch/resource/accounts.json#

POST bank/account/_bulk
測試數據

第四章 進階查詢

4.1 SearchAPI

  • ES支持兩種基本方式檢索

  • 官網查詢網址:https://www.elastic.co/guide/en/elasticsearch/reference/7.8/getting-started-search.html

    • 一種是通過使用REST requestAPI發送搜索參數(uri+搜索參數)

      GET /bank/_search?q=*&sort=account_number:asc
      #查找process索引下的所有數據以account_number字段進行升序排序,找到的數據都存放在hits命中記錄中,默認只返回10條記錄
      
    • 另一個是通過使用REST request body來發送請求(uri+請求體)

      #經常使用這種查詢方式
      GET /bank/_search
      {
        "query": { "match_all": {} },
        "sort": [
          { "account_number": "asc" }
        ]
      }
      

4.2 Query DSL

4.2.1 基本語法格式

  • Elasticsearch提供了一個可以執行查詢的json風格的DSL,這個被稱為Query DSL。該查詢語音非常全面

    #一個查詢語句的典型結構
    {
       QUERY_NAME:{
         ARGUMENT:VALUE
       }
    }
    #示例
    GET /bank/_search
    {
      "query": {
        "match_all": {}
      }
    }
    #如果是針對某個字段,那么它的結構如下:
    {
      QUERY_NAME:{
        FIELD_NAME:{
          	ARGUMENT:VALUE
        }
      }
    }
    #示例
    GET /bank/_search
    {
      "query": {
        "match_all": {}
      },
      "sort": [
        {
          "account_number": {
            "order": "desc"
          }
        }
      ]  
    }
    #分頁查詢
    GET /bank/_search
    {
      "query": {
        "match_all": {}
      },
      "sort": [
        {
          "account_number": {
            "order": "desc"
          }
        }
      ],
      "from": 0,  #從哪里開始
      "size": 5   #查詢幾條數據
    }
    

4.2.2 返回部分字段

GET /bank/_search
{
  "query": { "match_all": {} },
  "sort": [
    { "account_number": "asc" }
  ]
}
GET /bank/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "account_number": {
        "order": "desc"
      }
    }
  ],
  "from": 10,
  "size": 5,
  "_source": ["balance","firstname"]
}
#使用_source可以指定只返回某些字段

4.2.3 match匹配查詢

#基本類型(非字符串),精確匹配
GET bank/_search
{
  "query": {
    "match": {
      "address": "mill lane" #字段值會進行分詞匹配
    }
  }
}
#查找address字段值為mill lane;支持精確查詢和模糊查詢
#全文檢索會按照評分進行排序,會對檢索條件進行分詞匹配

4.2.4 match_phrase短語匹配

#將需要匹配的值當成一個整體單詞(不分詞)進行檢索
GET bank/_search
{
  "query": {
    "match_phrase": {
      "address": "mill lane"  #字段值不會分詞匹配
    }
  }
}

4.2.5 multi_match多字段匹配

#state字段或者address字段內容包含mill內容,字段內容會進行分詞處理
GET bank/_search
{
  "query": {
    "multi_match": {
      "query": "mill",  
      "fields": ["state","address"]
    }
  }
}

4.2.6 bool復合查詢

GET /bank/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "age": "40" } }
      ],
      "must_not": [
        { "match": { "state": "ID" } }
      ]
    }
  }
}
GET bank/_search
{
  "query": {
   "bool": {
     "must": [
       {"match": {
         "gender": "M"
       }},
       {"match": {
         "address": "Mill"
       }}
     ],
     "must_not": [
       {"match": {
         "age": "18"
       }}
     ],
     "should": [
       {"match": {
         "lastname": "wallace"
       }}
     ]
   }
  }
}
#must和must_not查詢結果必須同時滿足,should條件不滿足也能匹配,如果should條件也滿足的話,得分最高

4.2.7 filter結果過濾

#並不是所有的查詢都需要產生分數,特別是那些僅用於“filtering”(過濾)的文檔,為了不計算分數,es會自動檢查場景並且優化查詢的執行
GET  bank/_search
{
  "query": {
    "bool": {
      "must": [
        {"match": {
          "address": "mill"
        }}
      ],
      "filter": [
        {"range": {
          "age": {
            "gte": 20,
            "lte": 32
          }
        }}
      ]
    }
  }
}
#filter可以對上面條件輸出的結果進行過濾,並且不計算分數

4.2.8 term

#和match一樣,匹配某個屬性的值,全文檢索字段用match,其他非text字段匹配用term
GET bank/_search
{
  "query": {
    "match": {
      "age": "28"
    }
  }
}
GET bank/_search
{
  "query": {
    "term": {
      "age": "28"
    }
  }
}
#查詢字段值為非文本格式時,兩種查詢方法都可以;字段值為文本時,term無法使用
#精確匹配
GET bank/_search
{
  "query": {
    "match_phrase": {
      "address": "789 Madison Street"
    }
  }
}
#精確匹配
GET process/_search
{
  "query": {
    "match": {
      "address.keyword": "789 Madison Street"  #整個字段值的內容是全部,多或少都無法匹配
    }
  }
}

4.2.9 aggregations執行聚合

  • 聚合提供了從數據中分組和提取數據的能力,最簡單的聚合方法大致等於SQL GROUP BY和SQL聚合函數,在elasticsearch中,你有執行搜索返回hits(命中結果),並且同時返回聚合結果,把一個響應中的所有hits(命中結果)分隔開的能力,這是非常強大且有效的,你可以執行查詢和多個聚合,並且在一次使用中得到各自的返回結果,使用一次簡潔和簡化API來避免網絡回返
#搜索address中包含mill的所有人的年齡分布以及平均年齡,但不顯示這些人的詳情
GET  bank/_search
{
  "query": {
    "match": {
      "address": "mill"
    }
  },
  "aggs": {
    "age_agg": {
      "terms": {
        "field": "age",
        "size": 10
      }
    },
    "age_avg":{
      "avg": {
        "field": "age"
      }
    },
    "balanceavg": {
      "avg": {
        "field": "balance"
      }
    }
  }
}
#size: 0 不顯示搜索數據,只顯示聚合結果
aggs:執行聚合,聚合語法如下
"aggs":{
   "aggs_name":{  #這次聚合的名字,可自定義
      "agg_type":{ #可選聚合的類型(avg、term、terms)
          "field": "需要聚合的字段名"      
      }
   }
}
---------------------------------------------------------------------------
#按照年齡聚合,並且請求這些年齡段的這些人的平均薪資
GET bank/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "ageAgg": {
      "terms": {
        "field": "age",
        "size": 100
      },
      "aggs": {
        "ageAvg": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }    
  },
  "size": 0
}
-------------------------------------------------------------------------
#查出所有年齡分布,並且這些年齡段中的M的平均薪資和F的平均薪資,以及這個年齡段的總體平均薪資
GET bank/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "ageAgg": {
      "terms": {
        "field": "age",
        "size": 100
      },
      "aggs": {
        "genderagg": {
          "terms": {
            "field": "gender.keyword",
            "size": 10
          },
          "aggs": {
            "balanceAgg": {
              "avg": {
                "field": "balance"
              }
            }
          }
        },
        "ageBalanceAgg": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  }
}
#聚合text類型時,需要指定keyword

4.3 Mapping

4.3.1 字段類型

  • 核心類型
    • 字符串(string)
      • text
      • keyword
    • 數字類型(number)
      • long
      • integer
      • short
      • byte
      • double
      • float
      • half_float
      • scaled_float
    • 日期類型(date)
      • date
    • 布爾類型(Boolean)
      • boolean
    • 二進制類型(Binary)
      • binary
  • 復合類型
    • 數組類型(Array)
      • Array支持不針對特定的類型
    • 對象類型(Object)
      • object用於單json對象
    • 嵌套類型(Nested)
      • nested用於json對象數組
  • 地理類型
    • 地理坐標()
      • geo_point用於描述經緯度坐標
    • 地理圖形
      • geo_shape用於描述復雜形狀,如多邊形
  • 特定類型
    • IP類型
      • ip用於描述ipv4和ipv6特征
    • 補全類型
      • completion提供自動完成提示
    • 令牌計數類型
      • token_count用於統計字符串中的詞條數量
    • 附件類型
      • 參考mapper-attachements插件,支持將附件如Microsoft Office格式,Open Document格式,epub,HTML等等索引為attachment數據類型
    • 抽取類型
      • 接受特定領域查詢語言(query-dsl)的查詢

4.3.2 映射

  • mapping用來定義一個文檔,以及它所包含的屬性是如何存儲和索引的,比如使用mapping來定義

    • 哪些字符串字段應被視為全文字段。
    • 哪些字段包含數字、日期或地理位置。
    • 日期值 的格式
    • 自定義規則來控制動態添加字段的映射 es7版本去掉type概念
    • elasticsearch是基於lucene開發的搜索引擎,而es中不同type下名稱相同的filed最終在lucene中的處理方式是一樣的
    • 兩個不同type下的兩個user_name,在es同一個索引下其實被認為是同一個filed,你必須在兩個不同的type中定義相同的filed映射,否則,不同type中的相同字段名稱就會在處理中出現沖突的情況,導致lucene處理性能下降
    • 去掉type就是為了提高es處理數據的效率
    • es7.x版本中的type參數可選,比如索引一個文檔不再要求提供文檔類型,es8.x中不再支持type參數

4.3.3 新版本改變

  1. 查看索引mapping信息

    GET  bank/_mapping
    
  2. 創建索引,並指定映射關系

    PUT  /my_index
    {
      "mappings": {
        "properties": {
          "age":{"type": "integer"},
          "email":{"type": "keyword"},
          "name":{"type": "text"}
        }
      }
    }
    
  3. 添加新的字段映射

    PUT  /my_index/_mapping
    {
      "properties": {
        "employee-id" :{
          "type":"keyword",
          "index":"false"   #默認所有的字段都能夠被索引,如果配置false,則不能被檢索
        }
      }
    }
    
  4. 查看特定字段映射

GET /my_index/_mapping/field/employee-id 
  1. 更新映射

    • 對於已經存在的映射字段,我們不能更新,更新必須創建新的索引進行數據遷移
  2. 數據遷移

    • 把之前老銀行的數據轉移到新索引
    #先創建一個新的索引,並指定正確的字段映射關系
    PUT /newbank
    {
      "mappings": {
        "properties": {
          "account_number": {
            "type": "long"
          },
          "address": {
            "type": "keyword"
            },
          "age": {
            "type": "integer"
          },
          "balance": {
            "type": "long"
          },
          "city": {
            "type": "keyword"
          },
          "email": {
            "type": "keyword"
          },
          "employer": {
            "type": "text"
          },
          "firstname": {
            "type": "text"
          },
          "gender": {
            "type": "keyword"
          },
          "lastname": {
            "type": "text"
          },
          "state": {
            "type": "keyword"
          }
        }
      }
    }
    

數據轉移

POST  _reindex
{
  "source": {
    "index": "bank"
  }
  , "dest": {
    "index": "newbank"
  }
}

4.4 IK分詞器

  • 把一段中文或者別的划分成一個個的關鍵字,我們在搜索時候會把自己信息進行分詞,會把數據庫中或者索引中的數據進行分詞,然后再進行一個匹配操作,默認的中文分詞是將每個字看成一個詞,比如“我愛中國”會被分成“我”,“愛”,"中","國",這顯然是不符合要求的,所以我們需要安裝中文分詞器ik來解決這個問題
  • ik提供了兩個分詞算法:ik_smart和ik_max_word,其中ik_smart為最少切分,ik_max_word為最細粒度划分
#上傳軟件包並解壓文件到es的插件目錄中
[root@ceshi src]# ls
elasticsearch-7.8.0-linux-x86_64.tar.gz  elasticsearch-head-master.zip  kibana-7.8.0-linux-x86_64.tar.gz
elasticsearch-analysis-ik-7.8.0.zip      jdk-8u291-linux-x64.tar.gz
[root@ceshi src]# unzip  elasticsearch-analysis-ik-7.8.0.zip -d  /opt/es/plugins/ik/
#重啟es進程,並查看安裝的插件
[es@ceshi bin]$ ./elasticsearch-plugin list
future versions of Elasticsearch will require Java 11; your Java version from [/opt/jdk1.8.0_291/jre] does not meet this requirement
ik
  • 自己需要的詞,需要自己加到我們的分詞器字典中

    #創建一個my.dic文件,在字典中添加	
    <!--用戶可以在這里配置自己的擴展字典 -->
    	<entry key="ext_dict">my.dic</entry>
    #my.dic是我們自己創建的字典,以后的話,我們需要自己配置分詞就在自己定義的dic文件中進行配置即可!
    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM