一、关于es的介绍就不多少了,太多了,直接跳过,默认也有docker desktop环境了,参考官网自己安装也可,Elastic Observability and Security — built on Elasticsearch | Elastic
1.1 拉取es的镜像,写这篇的时候用的最新版8.7.0
docker pull docker.elastic.co/elasticsearch/elasticsearch:8.7.0
1.2 创建docker网络
docker network create elastic
1.3 运行容器
docker run -e ES_JAVA_OPTS="-Xms300m -Xmx300m" --name es01 --net elastic -p 9200:9200 -itd docker.elastic.co/elasticsearch/elasticsearch:8.7.0
博主电脑配置不咋地又只是demo,所以设置了jvm堆大小
1.4 这个版本会默认生成密码和证书指纹还有用于Kibana连接的token,当然你也可以重新生成,这些东西会打印在docker日志中,使用docker logs 容器id可查看日志,为了方便查看,可以导出查看
1.5如果没其他报错就可以通过http请求es的接口,因为默认开启了认证,所以可以在工具配置一下认证
二、使用.net core的NEST客户端操作es
NEST官方文档:Introduction | Elasticsearch .NET Clients [7.17] | Elastic
2.1 打开项目文件,添加NEST包
<PackageReference Include="NEST" Version="7.17.5" />
2.2 新建一个ElasticClientHelper类,用来连接es服务
private readonly IConfiguration _configuration;
private readonly ElasticClient _elasticClient;
public ElasticClientHelper(IConfiguration configuration)
{
_configuration=configuration;
_elasticClient = InitElasticClient();
}
private ElasticClient InitElasticClient()
{
Uri uri= new Uri("https://localhost:9200");
var settings = new ConnectionSettings(uri)
.CertificateFingerprint("656e023e9a394c670e0b056d55ad12c2b8d0bf6e9b2a7373fbd38fa711f2d460")
.BasicAuthentication(_configuration.GetSection("EsConfig")["UserName"], _configuration.GetSection("EsConfig")["Pwd"])
.EnableApiVersioningHeader();
var client = new ElasticClient(settings);
return client;
}
public ElasticClient GetElasticClient()
{
return _elasticClient;
}
}
2.2 官方文档建议使用单例的客户端,所以我们将ElasticClientHelper注入为单例的
services.AddSingleton<ElasticClientHelper>();
2.3 在控制器注入ElasticClientHelper
private readonly ElasticClientHelper _elasticClientHelper;
public EsController(
ElasticClientHelper elasticClientHelper
)
{
_elasticClientHelper = elasticClientHelper;
}
2.4 新增index_product索引并自动配置mapping,AutoMap方法会根据index_product类的属性自动映射为es的对应类型
/// <summary>
/// 创建索引
/// </summary>
/// <returns></returns>
[HttpGet("/CreateIndex")]
public async Task<IActionResult> CreateIndex()
{
var esClient = _elasticClientHelper.GetElasticClient();
var response = await esClient.Indices
.CreateAsync("index_product", option => option.Map(
map => map.AutoMap<index_product>()));
return Ok(response.IsValid);
}
public class index_product
{
public int Id { get; set; }
public string Name { get; set; }
public int Count { get; set; }
public bool Enable { get; set; }
public decimal Price { get; set; }
public DateTime CreateTime { get; set; }
}
2.5 调用接口后,使用kibana查看索引和mapping
kibana: GET index_product/_mapping
可以看到将我们定义的index_product类自动映射了
2.6 新增或修改索引文档
/// <summary>
/// 新增或更新文档
/// </summary>
/// <returns></returns>
[HttpPost("/InsertOrUpdateDoc")]
public async Task<IActionResult> InsertDoc(Product product)
{
var esClient = _elasticClientHelper.GetElasticClient();
var checkProduct =await _productContext.products.AnyAsync(a => a.Id == product.Id);
if(checkProduct)
{
var updateProduct= await _productContext.products.FirstAsync(a => a.Id == product.Id);
updateProduct = product;
}
else
{
await _productContext.products.AddAsync(product);
}
await _productContext.SaveChangesAsync();
var response = await esClient.IndexAsync(product, p => p.Index("index_product").Id(product.Id));
return Ok(response.IsValid);
}
这里数据库判断是否是新增或修改,防止出现数据库和Es的数据不一致问题
2.7 删除文档
/// <summary>
/// 删除文档
/// </summary>
/// <returns></returns>
[HttpPost("/DelDoc")]
public async Task<IActionResult> DelDoc(int productId)
{
DeleteRequest<Product> deleteRequest = new DeleteRequest<Product>("index_product", productId);
var esClient = _elasticClientHelper.GetElasticClient();
var delResult = await esClient.DeleteAsync(deleteRequest);
return Ok();
}
2.8简单查询
/// <summary>
/// 分页查询
/// </summary>
/// <returns></returns>
[HttpPost("/PageListDoc")]
public async Task<IActionResult> PageListDoc(int pageSize=10,int currentPage=1)
{
List<QueryContainer> querys = new List<QueryContainer>();
querys.Add(new MatchQuery()
{
Field="name",
Query="小米"
});
//querys.Add(new LongRangeQuery()
//{
// Field = "count",
// GreaterThan = 100
//});
SearchRequest<Product> searchRequest = new SearchRequest<Product>("index_product")
{
From = (currentPage - 1) * pageSize,
Size = pageSize,
Query =new BoolQuery()
{
Must= querys
},
Sort=new List<ISort>()
{
new FieldSort
{
Field="count",
Order=SortOrder.Ascending
}
}
};
var esClient = _elasticClientHelper.GetElasticClient();
var searchResult = await esClient.SearchAsync<Product>(searchRequest);
return Ok(searchResult.Documents);
}
上面分页查询name字段包含“小米”,且根据count字段排序排序。
如果要精确匹配text类型,而text默认有会将字段分词的,可以用 字段.keyword来精确匹配,查看name的mapping
例如:需要精确找出name等于小米手机的数据
使用 querys.Add(new MatchQuery()
{
Field="name",
Query="小米手机"
});是会将小米手机分词的,只要满足任一分词就会查询出来
可以改成:
querys.Add(new MatchQuery()
{
Field="name.keyword",
Query="小米手机"
})
这是最简单的使用了,NEST还有很多API需要去自己使用