dotNet Core 3.1 使用 Elasticsearch

Elasticsearch 是基於 Lucene 的搜索引擎。可以非常方便地實現分佈式的全文搜索,本文介紹在 dotNet Core 3.1 中怎樣使用  Elasticsearch 。

版本

  • dotnet Core :3.1

  • Elasticsearch:7.6.1

  • Kibana:7.6.1

  • NEST:7.10.1

  • Docker:19.03.13

Docker 安裝 Elasticsearch

爲了方便,我們以 Docker 的方式來進行安裝,這裏使用的版本爲 7.6.1,首先執行下面命令進行鏡像的拉取:

docker pull elasticsearch:7.6.1

注意:這裏需要指定相關版本,版本可以在 dockerhub 上進行查詢 ,否則拉鏡像的時候可能出現 下面錯誤:

Error response from daemon: manifest for elasticsearch:latest not found: manifest unknown: manifest unknown

鏡像成功拉取後,執行 docker run 命令構建容器,命令如下:

docker run -d --name myes -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" elasticsearch:7.6.1

爲了更好地進行中文的搜索,需要安裝中文分詞插件,本文中安裝的中文分詞插件爲 ik ,版本和 Elasticsearch 一致,安裝方法如下:

進入 Elasticsearch 容器後執行:

./bin/elasticsearch-plugin install [https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.6.1/elasticsearch-analysis-ik-7.6.1.zip](https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.5.4/elasticsearch-analysis-ik-6.5.4.zip)

安裝成功後的如下圖所示:

Docker 安裝 Kibana

Kibana 是一個免費的用戶界面,能夠讓您對 Elasticsearch 數據進行可視化,不是必須,但可以更好地查看數據。

執行下面命令進行鏡像的拉取,版本和 Elasticsearch 一致:

docker pull kibana:7.6.1

在宿主機創建 /root/data/elk/ 目錄並創建配置文件 kibana.yml ,內容如下:

# Default Kibana configuration for docker target
server.name: kibana
server.host: "0"
elasticsearch.hosts: [ "http://172.17.0.6:9200" ]
xpack.monitoring.ui.container.elasticsearch.enabled: true

elasticsearch.hosts 配置爲 Elasticsearch 的訪問地址。

執行下面命令進行容器的創建

docker run -d --restart=always --log-driver json-file --log-opt max-size=100m --log-opt max-file=2 --name mykibana -p 5601:5601 -v /root/data/elk/kibana.yml:/usr/share/kibana/config/kibana.yml kibana:7.6.1

創建成功後,可以通過 5601 端口進行訪問。

Elasticsearch 的 API

Elasticsearch 提供 API 的方式來進行數據操作,非常方便,常用的三個接口:

  • 插入數據

  • 獲取單條數據

  • 查詢數據

插入數據

http://10.211.55.6:9200/index/oec2003/1

  • index:我的理解是相當於數據庫表的概念;

  • oec2003:在 Elasticsearch 的 index 中有個 Type 的概念,相當於分組,當前的 7.6.1 版本中一個 index  中只能有一個 Type ,所以相當於可以忽略;

  • 1:單條記錄的 id;

  • 接口爲 Post 方式,數據內容爲 Json 格式,字段可以隨便定義,而且每條數據的字段可以不相同。

獲取單條數據

http://10.211.55.6:9200/index/oec2003/1

搜索數據

http://10.211.55.6:9200/index/oec2003/_search

  • 查詢接口爲 Post 方式;

  • 查詢表達式也是 Json 格式,如果熟悉 MongoDB 的 Document ,應該會感覺很熟悉。

在 dotNet Core 3.1 中使用

1、在 VS 2019 中創建 dotNet Core 3.1  的 WebAPI 項目 ElasticsearchWebAPIDemo ;

2、引用 Nuget 包 NEST;

3、創建一個 Elasticsearch 的客戶端連接接口和類,代碼如下:

class ESClientProvider : IESClientProvider
{
    private ElasticClient _client;
    public ESClientProvider()
    {
    }
    public ElasticClient GetClient()
    {
        if (_client != null)
            return _client;

        InitClient();
        return _client;
    }
    private void InitClient()
    {
        var node = new Uri("http://10.211.55.6:9200");
        _client = new ElasticClient(new ConnectionSettings(node).DefaultIndex("artiles"));
    }
}
public interface IESClientProvider
{
    ElasticClient GetClient();
}

4、在 Startup 類的 ConfigureServices 方法中將 ESClientProvider 類註冊爲單例

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IESClientProvider, ESClientProvider>();
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
    });
    services.AddControllers();
}

5、創建 Article 實體類


[ElasticsearchType(IdProperty = "Id")]
public class Article
{
   [Keyword]
   public string Id { get; set; }

   [Keyword]
   public string Title { get; set; }

   [Keyword]
   public string Auther { get; set; }

   [Keyword]
   public string SubTitle { get; set; }
} 

6、創建 ESController,添加創建 index 的方法

[HttpGet]
[Route("CreateIndex")]
public bool CreateIndex(string indexName)
{
    var res = _client.Indices.Create(indexName, c => c.Map<Article>(h => h.AutoMap().Properties(ps => ps
    .Text(s => s
         .Name(n => n.Title)
         .Analyzer("ik_smart")
         .SearchAnalyzer("ik_smart")
         )
    .Text(s => s
         .Name(n => n.SubTitle)
         .Analyzer("ik_smart")
         .SearchAnalyzer("ik_smart")
         )
    )
    ));
    return res.IsValid;
}
  • 對什麼字段進行索引需要進行指定

  • 字段的分詞器和搜索關鍵字的分詞器建議使用相同,否則可能搜索不到數據,例如上面代碼中都指定爲 ik_smart

7、添加 AddArticles 的方法

[HttpPost]
[Route("AddArticles")]
public bool AddArticles()
{
    // 獲取數據批量進行插入
    List<Article> listArticle = GetArticles();
   
    return _client.IndexMany(listArticle).IsValid;
}

8、添加高亮搜索的方法 SearchHighlight

[HttpPost]
[Route("SearchHighlight")]
public List<Article> SearchHighlight(string key, int pageIndex = 0, int pageSize = 10)
{
    var searchAll = _client.Search<Article>(s => s
      .From(pageIndex)
      .Size(pageSize)
      .Query(q => q
            .QueryString(qs => qs
            .Query(key)
            .DefaultOperator(Operator.Or)))
      .Highlight(h => h
            .PreTags("<span class='color:red;'>")
            .PostTags("</span>")
            .Encoder(HighlighterEncoder.Html)
            .Fields(
                fs => fs.Field(p => p.Title),
                fs => fs .Field(p => p.SubTitle)
            )
        )
      );

    foreach (var hit in searchAll.Hits)
    {
        foreach (var highlightField in hit.Highlight)
        {
            if (highlightField.Key == "title")
            {
                foreach (var highlight in highlightField.Value)
                {
                    hit.Source.Title = highlight.ToString();
                }
            }
            else if (highlightField.Key == "subTitle")
            {
                foreach (var highlight in highlightField.Value)
                {
                    hit.Source.SubTitle = highlight.ToString();
                }
            }
        }
    }

    return searchAll.Documents.ToList();
}

在 Kibana 中查看數據

Kibana 容器運行起來後,可以通過端口 5601 進行訪問,進行簡單配置就可以查看數據了,具體步驟如下:

1、進入 Management→ Index Management ,如下圖:

在改功能中可以維護所有的 idnex ,也可以看看我們創建的 index 有沒有在裏面顯示:

2、在 Index Patterns 中進行 index pattern 的添加,名字可以進行模糊匹配:

3、在 Discover 菜單中進行數據查看,在這裏可以選擇之前創建的 index pattern:

總結

本文只是很簡單的一個示例,帶你入門,有了基本概念後,深入學習更多的高級用法就很容易了,文章中部分示例代碼來自團隊中的王同學,在此感謝!

希望本文對您有所幫助!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章