net core 3.1使用ElasticSearch 全文搜索引擎
ElasticSearch 是一个开源的搜索引擎,建立在一个全文搜索引擎库 Apache Lucene 基础之上。 Lucene 可以说是当下最先进、高性能、全功能的搜索引擎库,无论是开源还是私有。
但是 Lucene 仅仅只是一个库。为了充分发挥其功能,你需要使用 Java 并将 Lucene 直接集成到应用程序中。 更糟糕的是,您可能需要获得信息检索学位才能了解其工作原理。Lucene 非常 复杂。
ElasticSearch 也是使用 Java 编写的,它的内部使用 Lucene 做索引与搜索,但是它的目的是使全文检索变得简单, 通过隐藏 Lucene 的复杂性,取而代之的提供一套简单一致的 RESTful API。
然而,Elasticsearch 不仅仅是 Lucene,并且也不仅仅只是一个全文搜索引擎。 它可以被下面这样准确的形容:
- 一个分布式的实时文档存储,每个字段 可以被索引与搜索
- 一个分布式实时分析搜索引擎
- 能胜任上百个服务节点的扩展,并支持 PB 级别的结构化或者非结构化数据
官方客户端在Java、.NET、PHP、Python、Ruby、Nodejs和许多其他语言中都是可用的。根据 DB-Engines 的排名显示,ElasticSearch 是最受欢迎的企业搜索引擎,其次是Apache Solr,也是基于Lucene。
Elasticsearch文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html
Elasticsearch.Net和Nest官方文档:https://www.elastic.co/guide/en/elasticsearch/client/net-api/7.x/index.html
一.安装
https://www.elastic.co/cn/downloads/下载elasticsearch和可视化工具kibana (两个版本号一定要一样) (下载慢用迅雷或者翻 Q)
1.(这一步忽略 因为我电脑没安装JDK 使用es自带得不香吗)环境配置 (注:Es自带jdk,如果没有特殊情况,可以使用es自带jdk,把java_home这个环境变量删除即可)
jdk下载,链接为:https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
选择对应版本的JDK

将下载好的jdk解压安装(请记住安装目录)
配置环境变量

然后点击系统变量下面的新建 (一定要是系统变量,上面的用户变量设置了是不会有效果的) 然后进行如下设置,确定好 就OK了,无需重启

2.下载ElasticSeach并解压运行
将下载好的Elasticsearch解压 然后到 bin 目录下 打开cmd窗口 输入.\elasticsearch 回车 就开始启动了,接下来在浏览器输入 localhost:9200,回车,显示下图的信息就OK了


在window服务(w+r 输入services.msc)里面就可以看到elasticsearch的服务了 立即启动 这样可以便捷进行启动的操作。

如果没有服务在ES文件夹的Bin目录下。打开cmd(同上方启动es的方法一致)输入.\elasticsearch-service.bat install 然后安装即可
如果不行输入 .\elasticsearch-service-x64 install 就会出现出现服务不能启动 报错 其中一种方法(安装java 1.8.0 jdk 再执行.\elasticsearch-service.bat install)
Es开启外网访问
9200端口开放外网访问,并修改配置文件。
修改配置文件:
打开根目录下的config文件夹,找到elasticsearch.yml
开启:
cluster.name: my-application
node.name: node-1
network.host: 0.0.0.0
http.port: 9200
cluster.initial_master_nodes: ["node-1"]
开启上面5个参数。注意host要修改成0.0.0.0。这五个参数必须都要开启。
3.安装Kibana到Window上(elasticsearch的可视化工具,类似于navicate)
Kibana 必须和你之前下载的 elasticsearch 版本一致。将下载好的kibana解压到你的 Elasticsearch的目录下

然后相同的方式,到kibana 的bin 目录下打开cmd 启动kibana就好了 输入 .\kibana.bat 操作完后。浏览器打开 localhost:5601 就可以访问kibana了
4.(可以不要)把Kibana安装成WindowSever
(1)下载NSSM,下载地址:http://www.nssm.cc/download
(2)将NSSM解压并将nssm.exe拷贝到kibana的bin\目录下
(3)cmd命令进入到kibana的bin文件夹下
(4)执行安装命令nssm install kibana。文件路径选中kibana.bat

点击安装即可
安装完成后就可以在服务里面看到该sever了
注:刚启动Kiabana时,出现 Kibana server is not ready yet 这个错误的话不要慌,稍等下再访问即可,该错误的意思是服务还没有完全启动。
Kibana开启外网访问 以及开启中文
到config文件夹下找到kibana.yml该配置文件
修改或者添加如下配置
server.port: 5601
server.host: "0.0.0.0"
i18n.locale: "zh-CN"
5.Elasticsearch 装完后可以打开 kibana 进行创建节点及测试使用了。部署完es的地址后。可以进行 .Net Core的部署了
6.IK分词器
下载对应的ik中文分词(https://github.com/medcl/elasticsearch-analysis-ik/releases)和英文分词(https://github.com/medcl/elasticsearch-analysis-pinyin/releases)拼音分词器:https://github.com/medcl/elasticsearch-analysis-pinyin
下载后复制到es的plugins 目录下,解压就行了

ik也可以自定义分词自己建一个文件放词语(详见github上的示例)

安装完成后需要重启 elasticsearch,然后测试分词器是否OK 有两种参考https://www.cnblogs.com/MrHSR/p/12258466.html
官方mapping制图文档 https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/fluent-mapping.html
//如果不存在该索引 就添加mapping制图的分词
if (!(await IndexExistsAsync(index)))
{
var createIndexResponse = _elasticClient.Indices.Create(index, c => c
.Map<BlogInfo>(m => m
.Properties(ps => ps
.Text(s => s.Name(s => s.Title).Analyzer("ik_smart"))//有两种ik_max_word
.Text(s => s.Name(s => s.Content).Analyzer("ik_smart"))
)
)
);
}
var response = await _elasticClient.IndexAsync(entity,
s => s.Index(index));
常用命令
GET _cat/indices 所有索引
GET blog/_search
{} 获取blog索引全部的文档 PUT /index 建立索引
POST /blog/_mapping
{
"properties": {
"content": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
} }
} 给ik搜索设置ik_max_word
DELETE blog 删除索引
GET blog查看当前索引
二.在Asp.netcore 上使用ElasticSearch
1..安装NuGet包,搜索Nest 并安装

2.开始使用
这里是以服务的方式进行实现的,经过测试ElasticSearch访问性能最高的是注册成单例服务,请求时要使用异步。这样性能可以提升到极致。
直接上代码

public interface IElasticsearchProvider
{
IElasticClient GetClient();
}
IElasticsearchProvider

public class ElasticsearchProvider : IElasticsearchProvider
{
public IElasticClient GetClient()
{
var url = AppSettings.Configuration["ElasticSearchContext:Url"];
//如果有多个节点以|分开
//var urls = url.Split('|').Select(x => new Uri(x)).ToList(); //单个节点
var connectionSettings = new ConnectionSettings(new Uri(url));
//多个节点
//var connectionPool = new SniffingConnectionPool(urls);
//var connectionSetting = new ConnectionSettings(connectionPool).DefaultIndex("");
//如果有账号密码
//connectionSettings.BasicAuthentication(UserName, Password); return new ElasticClient(connectionSettings);
}
}
ElasticsearchProvider

public interface IElasticsearchService
{
/// <summary>
/// 是否存在索引
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
Task<bool> IndexExistsAsync(string index = "blog"); /// <summary>
/// 新增数据
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entity"></param>
/// <param name="index"></param>
Task InsertAsync(BlogInfo entity, string index = "blog"); /// <summary>
/// 批量新增
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entity"></param>
/// <param name="index"></param>
Task InsertRangeAsync(IEnumerable<BlogInfo> entity, string index = "blog"); /// <summary>
/// 根据索引删除数据
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
Task RemoveIndex(string index = "blog");
/// <summary>
/// 根据索引删除数据 ID
/// </summary>
/// <param name="Id">实体ID</param>
/// <param name="index"></param>
/// <returns></returns>
Task DeleteAsync(string Id,string index = "blog");
/// <summary>
/// 修改
/// </summary>
/// <param name="Id"></param>
/// <param name="index"></param>
/// <returns></returns>
Task UpdateAsync(BlogInfo entity, string index = "blog");
/// <summary>
/// 查询
/// </summary>
/// <param name="page"></param>
/// <param name="limit"></param>
/// <param name="index"></param>
/// <returns></returns> Task<Tuple<int, IList<BlogInfo>>> QueryAsync(int page, int limit, string index = "blog");
}
IElasticsearchService

public class ElasticsearchService : IElasticsearchService
{
private readonly IElasticClient _elasticClient;
public ElasticsearchService(IElasticsearchProvider esClientProvider)
{
_elasticClient = esClientProvider.GetClient();
} public async Task<bool> IndexExistsAsync(string index="blog")
{
return (await _elasticClient.Indices.ExistsAsync(index)).Exists;
} public async Task InsertAsync(BlogInfo entity, string index = "blog")
{
//这里可判断是否存在
var response = await _elasticClient.IndexAsync(entity,
s => s.Index(index)); if (!response.IsValid)
throw new Exception("新增数据失败:" + response.OriginalException.Message);
} public async Task InsertRangeAsync(IEnumerable<BlogInfo> entity, string index = "blog")
{
var bulkRequest = new BulkRequest(index)
{
Operations = new List<IBulkOperation>()
};
var operations = entity.Select(o => new BulkIndexOperation<BlogInfo>(o)).Cast<IBulkOperation>().ToList();
bulkRequest.Operations = operations;
var response = await _elasticClient.BulkAsync(bulkRequest); if (!response.IsValid)
throw new Exception("批量新增数据失败:" + response.OriginalException.Message);
} public async Task UpdateAsync(BlogInfo entity, string index = "blog")
{
var response = await _elasticClient.UpdateAsync<BlogInfo>(entity.ID, x => x.Index(index).Doc(entity));
if (!response.IsValid)
throw new Exception("更新失败:" + response.OriginalException.Message);
} public async Task DeleteAsync(string Id, string index = "blog")
{
await _elasticClient.DeleteAsync<BlogInfo>(Id, x => x.Index(index));
} public async Task RemoveIndex(string index = "blog")
{
var exists = await IndexExistsAsync(index);
if (!exists) return;
var response = await _elasticClient.Indices.DeleteAsync(index); if (!response.IsValid)
throw new Exception("删除index失败:" + response.OriginalException.Message);
} public async Task<Tuple<int, IList<BlogInfo>>> QueryAsync(int page, int limit, string index = "blog")
{
var query = await _elasticClient.SearchAsync<BlogInfo>(x => x.Index(index)
.From((page - 1) * limit)
.Size(limit)
.Sort(x => x.Descending(v => v.CreateDate)));
return new Tuple<int, IList<BlogInfo>>(Convert.ToInt32(query.Total), query.Documents.ToList());
}
}
ElasticsearchService
3.在startup里面在ConfigureServices下面添加如下代码即可
services.AddScoped<IElasticsearchProvider, ElasticsearchProvider>();
services.AddTransient<IElasticsearchService, ElasticsearchService>();
按照新增、更新、删除、查询的顺序依次调用接口。新增可以多来几次,因为默认是没有数据的,多添加一点可以测试分页是否ok,这里就不再演示了。
3.1查询指定字段
var search = client.Search<AllInformationViewModel>(s => s
.Index(indexName)
.From(page)
.Size(10)
.Query(q => q
.Match(m => m
.Field(f => f.Title)
.Query(keyword))
3.2全文检索(包括全部字段我都查找,标题啊,描述啊,摘要啊)
var searchAll = client.Search<AllInformationViewModel>(s => s
.Index(indexName)
.From(page)
.Size(10)
.Query(q => q
.QueryString(qs => qs
.Query(keyword).DefaultOperator(Operator.And))
3.3全文检索查的标题,描述都得给我高亮
#方法1
.Highlight(h => h
.PreTags("<em>")
.PostTags("</em>")
.Encoder(HighlighterEncoder.Html)
.Fields(
fs => fs
.Field(p => p.Title), fs => fs
.Field(p => p.Content)
)
) #方法2
.Highlight(h => h
.Fields(
fs => fs
.Field(p => p.Title)
.PreTags("<em>")
.PostTags("</em>"), fs => fs
.Field(p => p.Content)
.PreTags("<em>")
.PostTags("</em>")
)
)
3.4高亮查询

public ActionResult Index(string keywords="")
{
var settings = new ConnectionSettings(new Uri("http://192.168.3.8:9200/")).DefaultIndex("article");
var client = new ElasticClient(settings); var search = client.Search<Article>(s => s
.From(0)
.Size(10)
.Query(q => q
.Match(m => m
.Field(f => f.Title)
.Query(keywords))
)
.Highlight(h => h.Fields(e => e.Field("title")
.PreTags("<b style='color:red'>")
.PostTags("</b>")))
//.Sort(r => r.Descending(q => q.CreateDate)) //在工作中把<b style='color:red'>这个换成em标签就可以了,然后在css里面给em加上高亮即可
); foreach (var hit in search.Hits)
{
foreach (var highlightField in hit.Highlight)
{
if (highlightField.Key == "title")
{
foreach (var highlight in highlightField.Value)
{
hit.Source.Title = highlight.ToString();
}
}
}
} return View(search.Documents);
}
如果你有安装kibana,现在可以满怀惊喜的去查看一下刚才添加的数据。
GET _cat/indices GET visitlogs/_search
{}

已经有大佬写好ES的增删改查的一个基础类库 (EasyElasticSearch)项目地址: https://github.com/wmchuang/EasyElasticSearch 博客地址https://www.cnblogs.com/mchuang/p/13678080.html
默认分词是一元分词 可以自己扩展就像以前的盘古分词一样 目前有个IK分词器https://github.com/medcl/elasticsearch-analysis-pinyin
搜索命令https://www.dazhuanlan.com/2019/09/14/1603cbb548bc/ https://www.cnblogs.com/yunquan/p/12934209.html
参考地址https://www.cnblogs.com/meowv/p/13614455.html
net core 3.1使用ElasticSearch 全文搜索引擎的更多相关文章
- Elasticsearch全文搜索引擎-PHP使用教程。
1.声明依赖关系: 比方说,你的项目中需要一个php版的elasticsearch框架.为了将它添加到你的项目中(下载),你所需要做的就是创建一个 composer.json 文件,其 ...
- 【Elasticsearch全文搜索引擎实战】之Head插件实践
简介 Elasticsearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elasticsearch是用Java开发的,并作为Ap ...
- ElasticSearch全文搜索引擎
一.ElasticSearch简介 1.1 什么是ElasticSearch ElasticSearch简称ES,其中Elastic 从名字里我们可以知道,ES的特点就在于灵活的搜索,其实E ...
- ElasticSearch全文搜索引擎(A)
文章:[Elasticsearch] 全文搜索 (一) - 基础概念和match查询 全文检索,是从最初的字符串匹配和简单的布尔逻辑检索技术,演进到能对超大文本.语音.图像.活动影像等非结构化数据进行 ...
- 【Elasticsearch全文搜索引擎实战】之集群搭建及配置
文中Elasticsearch版本为6.0.1 1. 环境配置 把环境配置放在第一节来讲,是因为很多人按官网的Getting Started安装运行会有各种错误.其实都是因为一些配置不正确引起的. 首 ...
- 【Elasticsearch全文搜索引擎实战】之Kibana搭建
1. Kibana介绍 Kibana是一个针对Elasticsearch的开源分析及可视化平台,用来搜索.查看交互存储在Elasticsearch索引中的数据.使用Kibana,可以通过各种图表进行高 ...
- 全文搜索引擎 ElasticSearch 还是 Solr?
最近项目组安排了一个任务,项目中用到了全文搜索,基于全文搜索 Solr,但是该 Solr 搜索云项目不稳定,经常查询不出来数据,需要手动全量同步,而且是其他团队在维护,依赖性太强,导致 Solr 服务 ...
- 全文搜索引擎Elasticsearch入门实践
全文搜索引擎Elasticsearch入门实践 感谢阮一峰的网络日志全文搜索引擎 Elasticsearch 入门教程 安装 首先需要依赖Java环境.Elasticsearch官网https://w ...
- Spring Boot 全文搜索引擎 ElasticSearch
参考 全文搜索引擎ElasticSearch 还是Solr? - JaJian - 博客园
随机推荐
- Spring 对Apache Kafka的支持与集成
1. 引言 Apache Kafka 是一个分布式的.容错的流处理系统.在本文中,我们将介绍Spring对Apache Kafka的支持,以及原生Kafka Java客户端Api 所提供的抽象级别. ...
- python+requests之接口测试
最近学习接口测试,测试工具玩的差不多了,想用代码来尝试一下. 发现一个简单的库,requests 一:安装 pip install requests 二:使用 import requests url ...
- Java基础教程——类和对象
视屏讲解:https://www.bilibili.com/video/av48272174 面向过程 VS 面向对象 面向过程:强调步骤. 面向对象:强调对象. 面向对象的特点就是:隐藏具体实现的细 ...
- 解决YUM下Loaded plugins: fastestmirror Determining fastest mirrors 的错误问题
最近想再购买一台虚拟服务器做项目测试,之前在西部数码购买的已经过期了,在同事的推荐下去搬瓦工购买了一台服务器,听他介绍在这里购买服务器很便宜($19.99/年)而且还是国外的,看着相比之前的确实挺便宜 ...
- Windows/Linux 代码共享,开发者称此举使Linux有了更差的结局
英特尔近期披露了 Linux 图形驱动程序相关的一些细节并指出,英特尔的图形驱动程序现在已在 Windows/Linux 之间共享约 60% 的代码库,90~100% 的性能. 针对此事,红帽公司的高 ...
- LaTeX中的特殊字符
空白符号代码及注释: 显示效果: 控制符.排版符号.标志符号.引号.连字符.非英文字符和重音符号的代码及注释: 显示效果:
- 前端vue小知识点
前端转后端Json数据 this.orderList=JSON.parse(resp.parameter)
- 2017 Mid Central Regional F.Orderly Class(大水题)
这两天刷了两道过去的原题,看看思维还是8太行. 这道题问给出两个字符串,要求只翻转一次,问有几种不同的方法使得a串变成b串 我一开始没看到只翻转一次,还以为是个计数 + 字符串dp大难题,心想当年的学 ...
- 第15.19节 PyQt(Python+Qt)入门学习:自定义信号与槽连接
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.引言 本文利用中介绍了PyQt中的信号和槽机制,除了使用PyQt组件的已有信号外,PyQt和Qt ...
- PyQt学习随笔:通过自定义类重写QApplication的notify方法捕获应用的所有消息
PyQt程序通过调用QApplication类的exec_()(sys.exit(app.exec_()) 进入程序主循环,开始处理事件,它从事件队列中获取本地窗口系统事件,将它们转化为 QEvent ...