.Net Core中使用ElasticSearch(一)


一、安裝配置

在官網下載Es,注意版本號,不同大版本號之間差異很大。我安裝的是7.14.0版本

1.1 安裝成服務

  cmd 進入bin目錄下執行

elasticsearch-service.bat install

1.2 安裝插件

  ik分詞器,分詞器的版本和ES版本需要一致

elasticsearch-plugin.bat install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.14.0/elasticsearch-analysis-ik-7.14.0.zip

1.3 配置賬號密碼

修改config目錄下面的elasticsearch.yml文件,在里面添加如下內容,並重啟。

xpack.security.enabled: true
xpack.license.self_generated.type: basic
xpack.security.transport.ssl.enabled: true

執行:

elasticsearch-setup-passwords interactive

然后配置每個賬戶密碼。

通過賬號密碼鏈接: http://username:password@127.0.0.1:9200

二、基礎概念

2.1 文檔元數據

節點

說明

_index

文檔存儲的地方,必須小寫,不能以下划線開頭,不能包含逗號

_type

文檔代表的對象的類,命名可以是大寫或者小寫,但是不能以下划線或者句號開頭,不應該包含逗號

_id

文檔的唯一標識

2.2 索引

一個 索引 類似於傳統關系數據庫中的一個 數據庫 ,是一個存儲關系型文檔的地方。事實上,我們的數據被存儲在分片(shards)中,索引只是一個把一個或多個分片分組在一起的邏輯空間。

2.3 文檔

文檔指最頂層結構或根對象序列化的JSON數據(以唯一Id標識並存儲於ES中),相當於關系數據的行。在版本7.0中已經沒有文檔了,統一為“_doc”。

三、數據的物理存儲

  ES為什么能搜索和存儲海量數據呢?是因為它的水平拓展,它內部分將整個數據進行分片,每個分片存儲部分數據。

 如圖:將整個數據分為5片,每一片都有一個副本,5個主分片分別存儲在不同節點。每個節點就是一個ElasticSearch實例。

 

3.1 數據是怎么存儲到分片中的?

  在創建索引時,主分片的數量和其副本的數量已經確定了,當創建文檔時,Es會根據文檔的Id值選擇一個主分片,可能這個主分片,在另一個節點。文檔被發送到主分片和該主分片所有的副分片中。在新建一個文檔的時候, Elasticsearch 如何知道一個文檔應該存放到哪個分片中呢?首先這肯定不會是隨機的,否則將來要獲取文檔的時候我們就不知道從何處尋找了。實際上,這個過程是根據下面這個公式決定的:

shard = hash(routing) % number_of_primary_shards

routing 是一個可變值,默認是文檔的 _id ,也可以設置成一個自定義的值。這就解釋了為什么我們要在創建索引的時候就確定好主分片的數量 並且永遠不會改變這個數量:因為如果數量變化了,那么所有之前路由的值都會無效,文檔也再也找不到了。

新建、索引、刪除操作,必須在主分片上完成后才能被復制到相關副分片。

3.2 多個節點查詢的過程

  當其中一個節點接收到搜索請求時,會將請求轉發到其他節點,然后將每個節點的結果聚集返回。在默認情況下,搜索請求通過round-robin輪詢機制選中主分片和副分片。

 

 

3.3 為什么ElasticSearch查詢快?

  Es為了查詢速度,使用的是倒排索引。假如存儲的兩個個文檔中Content字段值為:

  1:My nickname is Microheart.

  2:Hello Microheart

  為了創建倒排索引,Es首先將每個文檔的 content 值拆分成單獨的詞(也就是tokens),創建一個包含所有不重復詞條的排序列表,然后列出每個詞條出現在哪個文檔。

my

1

nickname

1

is

1

microheart

1,2

hello

2

 
 如果我們此時查詢 microheart ,2個文檔都會出現。但是文檔2的長度短,搜索詞條占比大,所以匹配度更高。倒排索引的特點就是不需要直接查詢內容,根據詞匹配,找到匹配文檔的Id。

3.4 相關性

  上面的例子,提到了相關性,相關性主要根據下面三個有關:

  • 檢索詞頻率:檢索詞在該字段出現的頻率,出現頻率越高,相關性也越高。 字段中出現過 5 次要比只出現過 1 次的相關性高。
  • 反向文檔頻率:每個檢索詞在索引中出現的頻率,頻率越高,相關性越低。檢索詞出現在多數文檔中會比出現在少數文檔中的權重更低。
  • 字段長度准則:字段的長度是多少?長度越長,相關性越低。 檢索詞出現在一個短的 title 要比同樣的詞出現在一個長的 content 字段權重更大。

3.5 映射

域映射:域最重要的屬性是type,就是字段類型。對於非string的域,只需要設置type

string域映射有兩個重要的屬性 index和 analyzer

Index:控制怎樣索引字符串

  • analyzed :首先分析字符串,然后索引它。換句話說,以全文索引這個域。
  • not_analyzed:索引這個域,所以它能夠被搜索,但索引的是精確值。不會對它進行分析。
  • no:不索引這個域。這個域不會被搜索到。

analyzer:指定分詞器

  上面的例子中,為什么會按照單詞拆詞呢?因為默認不指定分詞器,就是standard分詞器,它會按照英文單詞拆詞。分詞器有:snowball、standard、keyword、ik_smart、ik_max_word。其中ik_smart和ik_max_word是中文的分詞

 ES 2.x版本中只有string類型,ES 5.x以后,只有text 和 keyword字段。

比如一篇博客,有標題和內容兩個字段,指定為ik_smart。假如標題為 “.Net Core中使用ElasticSearch”,就會被拆詞為 “net”、“core”、 "中"、“使用”、“elasticsearch”。如果用戶搜索“.net core”,應該對用戶的搜索詞也進行拆詞,拆分為 “net”、“core”,那么標題就會命中。

        /// <summary>
        /// 標題
        /// </summary>
        [Text(Analyzer = "ik_smart")]
        public string Title { get; set; }

        /// <summary>
        /// 內容
        /// </summary>
        [Text(Analyzer = "ik_smart")]
        public string Content { get; set; }

 四、增刪改查

操作ElasticSearch是通過Resful api請求,所以我們可以通過Postman來實踐,也可以通過專業工具kibana操作

4.1 添加

POST product/_doc    
{
  "id": 2,
  "partNo": "KF2EDGK-5.08-5P",
  "brandName": "KEFA(科發)",
  "brandAlias": "KEFA(科發) 科發 KF科發 慈溪科發 KEFA"
}

 POST product/_doc/3
 {
  "id":3
  "partNo": "KF2EDGK-5.08-5P",
  "brandName": "KEFA(科發)",
  "brandAlias": "KEFA(科發) 科發 KF科發 慈溪科發 KEFA"
 }

兩種區別在於第一種未指定_id ,ElasticSearch會自動生成。第二種指定了_id的值 為3。

添加的數據會被ElasticSearch當做 “_source”字段的值存儲,除了_source字段,還有 _Index 、_type、_id 字段。

    {
        "_index" : "product",
        "_type" : "_doc",
        "_id" : "FHgny3wBBWoDytZQONAG",
        "_score" : 1.0,
        "_source" : {
          "id" : 2,
          "partNo" : "KF2EDGK-5.08-5P",
          "brandName" : "KEFA(科發)",
          "brandAlias" : "KEFA(科發) 科發 KF科發 慈溪科發 KEFA"
        }
      },
      {
        "_index" : "product",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 1.0,
        "_source" : {
          "id" : 3,
          "partNo" : "KF2EDGK-5.08-5P",
          "brandName" : "KEFA(科發)",
          "brandAlias" : "KEFA(科發) 科發 KF科發 慈溪科發 KEFA"
        }
      }

4.2 修改

PUT product/_doc/3   //更新整個文檔
{
  "id":3,
  "partNo": "123456",
  "brandName": "科發",
  "brandAlias": "KEFA(科發) 科發 KF科發 慈溪科發 KEFA"
}

POST product/_doc/3/_update  //更新部分文檔
{
  "doc": {
        "partNo": "654321"
    }
}

4.3 刪除

DELETE product  //刪除整個索引


DELETE product/_doc/1  //刪除_id為1的文檔

4.4 查詢

GET product/_doc/_search  //查詢所有
{
  "query": {
    "match_all": {}
  }
}

GET product/_doc/3   //查詢_id為3的文檔

查詢關聯的比較多,比較復雜,后面我們在慢慢聊。


免責聲明!

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



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