ElasticSearch入門 附.Net Core例子

1.什麼是ElasticSearch?

Elasticsearch是基於Lucene的搜索引擎。它提供了一個分佈式,支持多租戶的全文搜索引擎,它具備HTTP Web界面和無模式JSON文檔。 Elasticsearch是用Java開發的,根據Apache許可條款做爲開源發佈。html

----來自維基百科的解釋node

我我的的理解是Elasticsearch(如下簡稱ES)是一個支持分佈式的全文搜索引擎,由於在海量數據搜索時,普通關係型、非關係型數據庫由於IO讀取、處理器運算能力的限制,致使查詢效率難以提高,可是ES是分佈式的(能把處理壓力分攤給每一個節點),並且它是給每一個詞建立索引,因此查詢效率極高,堪稱即時搜索。git

並且ES能搭配Kibana,實現數據的可視化管理與數據分析。github

QQ截圖20180906215325

                                                                           Kibana儀表盤數據庫

2.ES中名詞概念

2.1 Node和Cluster

前面所過ES是一個分佈式搜索引擎,其本質是一個分佈式數據庫,能夠多臺計算機上的ES實例協同工做,這裏面的某一臺計算機上的某個ES實例,就能夠稱爲一個Node(節點),全部的這些協同工做的實例,能夠稱爲一個Cluster(集羣)。json

2.2 Index

Elastic 會索引全部字段,通過處理後寫入一個反向索引(Inverted Index)。查找數據的時候,直接查找該索引。api

因此,Elastic 數據管理的頂層單位就叫作 Index(索引)。它是單個數據庫的同義詞。每一個 Index (即數據庫)的名字必須是小寫。瀏覽器

2.3 Document

Index 裏面單條的記錄稱爲 Document(文檔)。許多條 Document 構成了一個 Index。服務器

Document 使用 JSON 格式表示,下面是一個例子。restful

{
  "user": "張三",
  "title": "工程師",
  "desc": "數據庫管理"
}

同一個 Index 裏面的 Document,不要求有相同的結構(scheme),可是最好保持相同,這樣有利於提升搜索效率。

2.4 Type

Document 能夠分組,好比weather這個 Index 裏面,能夠按城市分組(北京和上海),也能夠按氣候分組(晴天和雨天)。這種分組就叫作 Type,它是虛擬的邏輯分組,用來過濾 Document。

不一樣的 Type 應該有類似的結構(schema),舉例來講,id字段不能在這個組是字符串,在另外一個組是數值。這是與關係型數據庫的表的一個區別。性質徹底不一樣的數據(好比productslogs)應該存成兩個 Index,而不是一個 Index 裏面的兩個 Type(雖然能夠作到)。

根據規劃,Elastic 6.x 版只容許每一個 Index 包含一個 Type,7.x 版將會完全移除 Type。

----參考阮一峯 全文搜索引擎 Elasticsearch 入門教程

3.ES工做原理

Elasticsearch用於構建高可用和可擴展的系統。擴展的方式能夠是購買更好的服務器(縱向擴展)或者購買更多的服務器(橫向擴展)。

Elasticsearch雖然能從更強大的硬件中得到更好的性能,可是縱向擴展有它的侷限性。真正的擴展應該是橫向的,它經過增長節點來均攤負載和增長可靠性。若是咱們啓動一個單獨的節點,它尚未數據和索引,這個集羣看起來就像下圖。

集羣中一個節點會被選舉爲主節點(master),它將臨時管理集羣級別的一些變動,例如新建或刪除索引、增長或移除節點等。

主節點不參與文檔級別的變動或搜索,這意味着在流量增加的時候,該主節點不會成爲集羣的瓶頸。任何節點均可以成爲主節點。咱們例子中的集羣只有一個節點,因此它會充當主節點的角色。

當索引建立完成的時候,主分片的數量就固定了,可是複製分片的數量能夠隨時調整。

讓咱們在集羣中惟一一個空節點上建立一個叫作 blogs 的索引。默認狀況下,一個索引被分配5個主分片,可是爲了演示的目的,咱們只分配3個主分片和一個複製分片(每一個主分片都有一個複製分片):

PUT /blogs

{

"settings" : {

"number_of_shards" : 3,

"number_of_replicas" : 1

}

}

咱們的集羣如今看起來就像上圖,三個主分片都被分配到 Node 1 。

在單一節點上運行意味着有單點故障的風險:沒有數據備份。幸運的是,要防止單點故障,咱們惟一須要作的就是啓動另外一個節點。

若是咱們啓動了第二個節點,這個集羣看起來就像下圖

第二個節點已經加入集羣,三個複製分片(replica shards)也已經被分配了,分別對應三個主分片,這意味着在丟失任意一個節點的狀況下依舊能夠保證數據的完整性。

文檔的索引將首先被存儲在主分片中,而後併發複製到對應的複製節點上。這能夠確保咱們的數據在主節點和複製節點上均可以被檢索。

隨着應用需求的增加,咱們該如何擴展?若是咱們啓動第三個節點,咱們的集羣會自我感知,這時便成爲了三節點集羣。

分片已經被從新分配以平衡負載:

從 Node 1 和 Node 2 來的分片已經被移動到新的 Node 3 上,這樣每一個節點就有兩個分片,以代替以前的三個。這意味着每一個節點的硬件資源(CPU、RAM、I/O)被較少的分片共享,這樣每一個分片就會有更好的表現。

分片自己就是一個完整成熟的搜索引擎,它可使用單一節點的全部資源。使用這6個分片(3個主分片和三個複製分片)咱們能夠擴展最多到6個節點,每一個節點上有一個分片,這樣就能夠100%使用這個節點的資源了。

----參考文獻Elasticsearch: 權威指南

4.ES的安裝與使用

4.1安裝

由於每一個平臺上ES安裝方法有所區別,並且網絡上有較爲詳細的安裝教程,本文在此再也不贅述。本來是想着在個人兩臺騰訊雲Centos服務器上,搭建一個ES集羣的,可是由於雲服務器內存1G,運行ES時老是報錯,大致意思是內存不足,因此我就在本身的PC上,只搭建了一個ES節點,還不算ES集羣,不過不影響功能的測試。

Windows環境下ES 6.4 MSI下載地址:https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.4.0.msi

一路默認下一步,安裝完成後,在瀏覽器地址輸入http://localhost:9200/,若是您能看到下列結果,說明安裝完成。

{
    "name": "DESKTOP-1FC1B1D",
    "cluster_name": "elasticsearch",
    "cluster_uuid": "lZx4n2xzToeaj9k3HEHAqw",
    "version": {
        "number": "6.4.0",
        "build_flavor": "unknown",
        "build_type": "unknown",
        "build_hash": "595516e",
        "build_date": "2018-08-17T23:18:47.308994Z",
        "build_snapshot": false,
        "lucene_version": "7.4.0",
        "minimum_wire_compatibility_version": "5.6.0",
        "minimum_index_compatibility_version": "5.0.0"
    },
    "tagline": "You Know, for Search"
}

"You Know, for Search"

ES有一套Restful 風格的API系統,經過該API咱們與ES進行交互。

4.2數據的提交

利用PostMan向ES POST一條數據以下。

image

http://localhost:9200/index/test1/1 中Index是該數據的Index(上文有介紹Index),test1是該數據的Type,1是該條數據的Id,該ID在經過ID獲取數據時須要用到。

4.3數據經過ID獲取

在知道數據的Index,Type和ID的狀況下,能夠經過和上文Post數據的Url同樣的格式獲取數據,不一樣之處時,此時的HTTP方法時Get,以下:

image

4.4數據的查詢

ES的數據查詢語法較爲豐富,此處以一個最簡單的查詢爲例,Http方法爲POST,請求的Url中一樣指定了Index和Type

{
   "query" : { "match" : { "tagline" : "for" }}
}

指的時查詢tagline中包含的for的數據,

image

其餘更詳細的查詢語法,建議你們查看Elasticsearch: 權威指南,此處主要拋磚引玉。

5.Net Core中使用ES

在上文中,咱們瞭解到,能夠經過restful api與ES進行交互,那麼,若是須要在咱們的程序中使用ES,是否是要建立一個這樣的Helper方法,經過HTTP調用RESTFul API與ES進行交互呢?

不是不能夠,可是Elastic爲大部分語言都建立了"Clients」,其實就是把上文說起的那些方法進行了一個封裝,是咱們在代碼中,可以方便地調用ES。

以.Net Core爲例,該」Clients」開源在Github:

https://github.com/elastic/elasticsearch-net

5.1 SDK(客戶端,Clients)

在該倉庫中,其實有Elasticsearch.NetNEST兩個.Net官方SDK,兩個各有特點。

Elasticsearch.Net 是一個很是low leave並且靈活的SDK,它不在乎你如何的構建本身的請求和響應。它很是抽象,所以全部的Elasticsearch RESTFul API被表示爲方法,並且不會影響你構建json / request / response對象的方式。 它還內置可配置/可覆蓋的羣集故障轉移重試機制。

NEST 是一個 high level SDK, 有很是大的彈性,若是你想更好的提高你的搜索服務,你徹底可使用它來作爲你的客戶端。能夠映射全部請求和響應對象,擁有一個強類型DSL(領域特定語言),而且可使用.net的特性,如協變、Auto Mapping Of POCOs,NEST內部使用的依然是Elasticsearch.Net客戶端。

5.2建立一個Demo

本Demo我使用的NEST,因此第一步是建立一個Asp.Net Core Api應用程序並引入NEST的Nuget包。

PM> Install-Package NEST

 

而後我建立一個EsClientProvider,代碼以下:

public class EsClientProvider : IEsClientProvider
    {
        private readonly IConfiguration _configuration;
        private ElasticClient _client;
        public EsClientProvider(IConfiguration configuration)
        {
            _configuration = configuration;
        }

        public ElasticClient GetClient()
        {
            if (_client != null)
                return _client;

            InitClient();
            return _client;
        }

        private void InitClient()
        {
            var node = new Uri(_configuration["EsUrl"]);
            _client = new ElasticClient(new ConnectionSettings(node).DefaultIndex("demo"));
        }
    }

 

IEsClientProvider代碼以下:

public interface IEsClientProvider
    {
        ElasticClient GetClient();
    }

 

而後再Startup的ConfigureServices進行服務的註冊

public void ConfigureServices(IServiceCollection services)
        {

            services.AddSingleton<IEsClientProvider, EsClientProvider>();

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        }

 

最後,修改ValueContoller,代碼以下:

public class ValueController : ControllerBase
    {
        private readonly ElasticClient _client;

        public ValueController(IEsClientProvider clientProvider)
        {
            _client = clientProvider.GetClient();
        }

        [HttpPost]
        [Route("value/index")]
        public IIndexResponse Index(Post post)
        {
            return _client.IndexDocument(post);
        }

        [HttpPost]
        [Route("value/search")]
        public IReadOnlyCollection<Post> Search(string type)
        {
            return _client.Search<Post>(s => s
                .From(0)
                .Size(10)
                .Query(q => q.Match(m => m.Field(f => f.Type).Query(type)))).Documents;
        }
    }

 

其中Index方法能進行數據的提交,Search是經過Post實體的type來進行數據查詢。

 

代碼不復雜,我就不詳細介紹了,在PostMan中進行Search方法的測試,效果以下:

image

查詢要求是type是567,響應的實體中,type確實爲567,Success!

 

項目完整代碼:https://github.com/liuzhenyulive/Elasticsearch.Net-Demo

 

不按期分享.Net實用乾貨,歡迎關注Open-mouthed smile

相關文章
相關標籤/搜索