dotNet Core 3.1 使用 Elasticsearch

Elasticsearch 是基于 Lucene 的搜索引擎??梢苑浅7奖愕貙?shí)現(xiàn)分布式的全文搜索,本文介紹在 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 的方式來進(jìn)行安裝,這里使用的版本為 7.6.1,首先執(zhí)行下面命令進(jìn)行鏡像的拉?。?/p>
docker?pull?elasticsearch:7.6.1
注意:這里需要指定相關(guān)版本,版本可以在 dockerhub 上進(jìn)行查詢 ,否則拉鏡像的時(shí)候可能出現(xiàn) 下面錯(cuò)誤:
Error?response?from?daemon:?manifest?for?elasticsearch:latest?not?found:?manifest?unknown:?manifest?unknown
鏡像成功拉取后,執(zhí)行 docker run 命令構(gòu)建容器,命令如下:
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
為了更好地進(jìn)行中文的搜索,需要安裝中文分詞插件,本文中安裝的中文分詞插件為 ik ,版本和 Elasticsearch 一致,安裝方法如下:
進(jìn)入 Elasticsearch 容器后執(zhí)行:
./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 是一個(gè)免費(fèi)的用戶界面,能夠讓您對(duì) Elasticsearch 數(shù)據(jù)進(jìn)行可視化,不是必須,但可以更好地查看數(shù)據(jù)。
執(zhí)行下面命令進(jìn)行鏡像的拉取,版本和 Elasticsearch 一致:
docker?pull?kibana:7.6.1
在宿主機(jī)創(chuàng)建 /root/data/elk/ 目錄并創(chuàng)建配置文件 kibana.yml ,內(nèi)容如下:
#?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 的訪問地址。
執(zhí)行下面命令進(jìn)行容器的創(chuàng)建
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
創(chuàng)建成功后,可以通過 5601 端口進(jìn)行訪問。
Elasticsearch 的 API
Elasticsearch 提供 API 的方式來進(jìn)行數(shù)據(jù)操作,非常方便,常用的三個(gè)接口:
- 插入數(shù)據(jù)
- 獲取單條數(shù)據(jù)
- 查詢數(shù)據(jù)
插入數(shù)據(jù)
http://10.211.55.6:9200/index/oec2003/1

- index:我的理解是相當(dāng)于數(shù)據(jù)庫(kù)表的概念;
- oec2003:在 Elasticsearch 的 index 中有個(gè) Type 的概念,相當(dāng)于分組,當(dāng)前的 7.6.1 版本中一個(gè) index ?中只能有一個(gè) Type ,所以相當(dāng)于可以忽略;
- 1:?jiǎn)螚l記錄的 id;
- 接口為 Post 方式,數(shù)據(jù)內(nèi)容為 Json 格式,字段可以隨便定義,而且每條數(shù)據(jù)的字段可以不相同。
獲取單條數(shù)據(jù)
http://10.211.55.6:9200/index/oec2003/1

搜索數(shù)據(jù)
http://10.211.55.6:9200/index/oec2003/_search

- 查詢接口為 Post 方式;
- 查詢表達(dá)式也是 Json 格式,如果熟悉 MongoDB 的 Document ,應(yīng)該會(huì)感覺很熟悉。
在 dotNet Core 3.1 中使用
1、在 VS 2019 中創(chuàng)建 dotNet Core 3.1 ?的 WebAPI 項(xiàng)目 ElasticsearchWebAPIDemo ;
2、引用 Nuget 包 NEST;
3、創(chuàng)建一個(gè) 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 類注冊(cè)為單例
public?void?ConfigureServices(IServiceCollection?services)
{
????services.AddSingleton();
????services.AddSwaggerGen(c?=>
????{
????????c.SwaggerDoc("v1",?new?OpenApiInfo?{?Title?=?"My?API",?Version?=?"v1"?});
????});
????services.AddControllers();
}
5、創(chuàng)建 Article 實(shí)體類
[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、創(chuàng)建 ESController,添加創(chuàng)建 index 的方法
[HttpGet]
[Route("CreateIndex")]
public?bool?CreateIndex(string?indexName)
{
????var?res?=?_client.Indices.Create(indexName,?c?=>?c.Map(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;
}
- 對(duì)什么字段進(jìn)行索引需要進(jìn)行指定
- 字段的分詞器和搜索關(guān)鍵字的分詞器建議使用相同,否則可能搜索不到數(shù)據(jù),例如上面代碼中都指定為 ik_smart
7、添加 AddArticles 的方法
[HttpPost]
[Route("AddArticles")]
public?bool?AddArticles()
{
????//?獲取數(shù)據(jù)批量進(jìn)行插入
????List?listArticle?=?GetArticles();
???
????return?_client.IndexMany(listArticle).IsValid;
}
8、添加高亮搜索的方法 SearchHighlight
[HttpPost]
[Route("SearchHighlight")]
public?List?SearchHighlight(string?key,?int?pageIndex?=?0,?int?pageSize?=?10)
{
????var?searchAll?=?_client.Search(s?=>?s
??????.From(pageIndex)
??????.Size(pageSize)
??????.Query(q?=>?q
????????????.QueryString(qs?=>?qs
????????????.Query(key)
????????????.DefaultOperator(Operator.Or)))
??????.Highlight(h?=>?h
????????????.PreTags("")
????????????.PostTags("")
????????????.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 中查看數(shù)據(jù)
Kibana 容器運(yùn)行起來后,可以通過端口 5601 進(jìn)行訪問,進(jìn)行簡(jiǎn)單配置就可以查看數(shù)據(jù)了,具體步驟如下:
1、進(jìn)入 Management→ Index Management ,如下圖:

在改功能中可以維護(hù)所有的 idnex ,也可以看看我們創(chuàng)建的 index 有沒有在里面顯示:

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

3、在 Discover 菜單中進(jìn)行數(shù)據(jù)查看,在這里可以選擇之前創(chuàng)建的 index pattern:

總結(jié)
本文只是很簡(jiǎn)單的一個(gè)示例,帶你入門,有了基本概念后,深入學(xué)習(xí)更多的高級(jí)用法就很容易了,文章中部分示例代碼來自團(tuán)隊(duì)中的王同學(xué),在此感謝!
希望本文對(duì)您有所幫助!
