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不支持的场景:
1、 不支持事务
2、 不支持多表关联查询业务
3、不适合频繁更新的业务场景, 读写有一定延时,写入的数据,最快1s能被检索到
默认情况下每个分片会每秒自动刷新一次,也就是说文档从Index请求到对外可见能够被搜到,最少要1秒钟,网络和CPU再快也不行。这么做是Lucene为了提高写操作的吞吐量而做出的延迟牺牲,当然这个设置是可以手动调整的,但是并不建议你去动它,会极大地影响搜索性能,刷新频率太高也会导致集群陷入瘫痪。不同的应用对实时性的定义并不一样,这取决于需求。
开始ElasticSearch之旅
1.创建 ASP.NET Core Web API 项目
创建net Core项目,将其命名为:ElasticSearchDemo,创建项目后,通过NuGet库引入Nest包
2.添加实体模型
将 ES.Models目录添加到项目根目录下
使用以下代码将 FamousPoemsModel类添加到 ES.Models 目录
using System;
namespace ES.Models
{
///
///
///
public class FamousPoemsModel
{
///
///
///
public FamousPoemsModel()
{
}
///
///
///
public string Id { get; set; }
///
/// 作者
///
[Nest.Keyword]
public string vcAuthor { get; set; }
///
/// 内容
///
[Nest.Keyword]
public string vcContent { get; set; }
///
/// 标题
///
[Nest.Keyword]
public string vcTitle { get; set; }
///
/// 创建时间
///
public DateTime dtCreateTime { get; set; }
///
/// 更新时间
///
public DateTime dtUpdateTime { get; set; }
}
}
3.添加配置模型
appsettings.json 添加以下ElasticSearch配置
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ElasticSearch": {
"Uri": "http://es-cn-zvp2asu64001ta726.public.elasticsearch.aliyuncs.com:9200",
"UserName": "elastic",
"Password": "es123456@"
}
}
4.创建ES.Business目录,在目录下创建ElasticSearch、IService、Service目录,废话不多说,直接上代码
using ES.Business.IService;
using ES.Core;
using ES.Models;
using Nest;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ES.Business.Service
{
///
///
///
public class FamousPoemsService : IFamousPoemsService, ITransientDependency
{
///
///
///
private readonly IEsUpdateService _updateService;
///
///
///
private readonly IEsClientService _clientService;
///
///
///
private readonly IEsIndexService _indexService;
///
///
///
///
///
///
public FamousPoemsService(IEsUpdateService updateService, IEsClientService clientService, IEsIndexService indexService)
{
_updateService = updateService;
_clientService = clientService;
_indexService = indexService;
}
///
/// 删除
///
///
///
public async Task DeleteAsync(string Id)
{
var mustFilters = new List, QueryContainer>>();
mustFilters.Add(t => t.Match(m => m.Field(f => f.Id).Query(Id)));
var result = await _clientService.Client.DeleteByQueryAsync(x => x.Index("famouspoemsmodel")
.Query(q => q.Bool(b => b.Must(mustFilters))));
return result.Deleted;
}
///
/// 根据相关条件获取分页数据
///
///
///
public async Task> GetPageAsync(ParameterModel dto)
{
PageModel pageModel = new PageModel();
var mustFilters = new List, QueryContainer>>();
if (!string.IsNullOrEmpty(dto.vcTitle))
{
mustFilters.Add(t => t.Match(m => m.Field(f => f.vcTitle).Query(dto.vcTitle)));
}
if (dto.authors.Count() > 0)
{
mustFilters.Add(t => t.Terms(m => m.Field(f => f.vcAuthor).Terms(dto.authors.ToArray())));
}
var total = await _clientService.Client.CountAsync(x => x.Index("famouspoemsmodel")
.Query(q => q.Bool(b => b.Must(mustFilters))));
if (total.Count == 0)
{
return pageModel;
}
pageModel.nDataCount = Convert.ToInt32(total.Count);
pageModel.nPageCount = (int)Math.Ceiling((double)pageModel.nDataCount / dto.nPageSize);
dto.nPageIndex = ((dto.nPageIndex <1 ? 1 : dto.nPageIndex) - 1) * dto.nPageSize;
var data = await _clientService.Client.SearchAsync(x => x.Index("famouspoemsmodel")
.Query(q => q.Bool(b => b.Must(mustFilters))).Sort(s => s.Ascending(d => d.dtCreateTime)).From(dto.nPageIndex).Size(dto.nPageSize));
pageModel.data = (List)data.Documents;
return pageModel;
}
///
/// 新增数据
///
///
///
public async Task InsertAsync(FamousPoemsModel poems)
{
return await _indexService.InsertAsync(poems);
}
///
/// 新增批量数据
///
///
///
public async Task InsertRangeAsync(List poems)
{
return await _indexService.InsertRangeAsync(poems);
}
///
/// 通过主键局部更新数据
///
///
///
///
public async Task UpdateAsync(string nId, string vcTitle)
{
FamousPoemsModel dto = new FamousPoemsModel();
dto.vcTitle = vcTitle;
dto.dtUpdateTime = DateTime.Now;
var result = _updateService.Update(nId, dto);
return result.IsValid;
}
///
/// 通过条件批量局部更新某个字段数据
///
///
public async Task UpdateByAuthorAsync(string vcAuthor)
{
var mustFilters = new List, QueryContainer>>();
mustFilters.Add(t => t.Match(m => m.Field(f => f.vcAuthor).Query(vcAuthor)));
var result = await _clientService.Client.UpdateByQueryAsync(q => q.Index("famouspoemsmodel")
.Query(q => q.Bool(t => t.Must(mustFilters)))
.Script(script => script.Source("ctx._source.dtUpdateTime=" + DateTime.Now + ";")));
return result.IsValid;
}
}
}
5.将以下代码添加到 Startup.ConfigureServices
#region ES配置
services.AddEsService(optiOns=>
{
options.Urls = Configuration["ElasticSearch:Uri"];
options.UserName = Configuration["ElasticSearch:UserName"];
options.Password = Configuration["ElasticSearch:Password"];
});
#endregion
6.添加控制器
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ES.Business.IService;
using ES.Models;
using ES.Util;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
namespace ES.Web.Controllers
{
///
/// 属性注入
///
public class PoemsController : ControllerBase
{
///
///
///
public IFamousPoemsService famousPoemsService { get; set; }
///
/// 插入单条数据
///
///
///
[HttpPost("Poems/InsertAsync")]
public async Task InsertAsync([FromBody]FamousPoemsModel poems)
{
return Content(JsonConvert.SerializeObject(await famousPoemsService.InsertAsync(poems)));
}
///
/// 批量插入数据
///
///
///
[HttpPost("Poems/InsertRangeAsync")]
public async Task InsertRangeAsync([FromBody]List poems)
{
return Content(JsonConvert.SerializeObject(await famousPoemsService.InsertRangeAsync(poems)));
}
///
///
///
///
///
[HttpPost("Poems/DeleteAsync")]
public async Task DeleteAsync(string Id)
{
return Content(JsonConvert.SerializeObject(await famousPoemsService.DeleteAsync(Id)));
}
///
/// 更新
///
///
///
///
[HttpPost("Poems/UpdateAsync")]
public async Task UpdateAsync(string Id, string vcTitle)
{
return Content(JsonConvert.SerializeObject(await famousPoemsService.UpdateAsync(Id, vcTitle)));
}
///
/// 批量更新
///
///
///
[HttpPost("Poems/UpdateByAuthorAsync")]
public async Task UpdateByAuthorAsync(string vcAuthor)
{
return Content(JsonConvert.SerializeObject(await famousPoemsService.UpdateByAuthorAsync(vcAuthor)));
}
///
/// 根据相关条件获取分页数据
///
///
///
[ProducesResponseType(typeof(FamousPoemsModel), 200)]
[HttpPost("Poems/GetPageAsync")]
public async Task GetPageAsync([FromBody]ParameterModel dto)
{
return Content(JsonConvert.SerializeObject(await famousPoemsService.GetPageAsync(dto)));
}
}
}
本示例代码gitee地址:https://gitee.com/fan_zhongtuan/elasticsearchdemo.git
阿里云ElasticSearch新用户0员免费试用地址:https://www.aliyun.com/product/bigdata/elasticsearch
Elasticsearch官方权威文档:https://www.elastic.co/guide/cn/elasticsearch/guide/current/foreword_id.html