大家好,我是Edison。

上一篇:Logstash数据采集

写在开头

有了前面10篇的基础,我们大概清楚了ES的基本概念和使用(主要是查询),这也是我们作为Developer应该了解的范畴,而至于更深入的聚合分析、运维管理就不在本系列的范畴中。有童鞋说,讲讲如何在.NET应用中集成和使用ES吧,额,这个其实网上也有很多教程了。不过你既然提了,那还是得安排上。

在.NET应用中集成ES一般涉及两个方面:

(1)将ES当存储用,类似于MongoDB,做文档的增删查改,这一类操作偏CRUD。

(2)对ES中的数据做查询分析,聚合统计、分组等等,这一类操作偏查询分析。

针对这两类操作,我们今天先来搞定CRUD!

准备工作

创建一个Web API应用程序,这里我选择的是.NET 6版本。

项目结构如下图所示:

其中,我们对Elastic的集成主要放在了Infrastructure目录中,里面存放了我们定义的Repository进而帮助我们在Controller中使用其提供的持久化能力。
在appsetting中我们定义了如下配置指明Elastic的相关信息(URL地址 和 默认索引):

{
......
"Elastic": {
"ServerUrl": "http://edt-elastic:9200",
"DefaultIndex": "app-logs"
}
}

定义模型

我们这里定义一个Model,假设叫AppLog,来模拟日志文档的CRUD到ES:

public class AppLog : ElasticModelBase
{
public string LogLevel { get; set; } = "Info";
public string Message { get; set; } = string.Empty;
public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.Now; public AppLog()
{
this.Id = Guid.NewGuid().ToString();
} public AppLog(string id)
{
this.Id = id;
}
} public class ElasticModelBase
{
public virtual string Id { get; set; }
}

定义ElasticProxy

我们知道,.NET应用要操作Elastic得使用Elastic的.NET客户端,因此按照国际惯例我们对其进行一个小封装,以便于可以在Repository中使用。

对于ES 7.x版本的集群,推荐使用NEST这个客户端包(目前已停止更新):

dotnet add package NEST

对于ES 8.x及以上版本的集群,则推荐使用Elastic.Clients.Elasticsearch:

dotnet add package Elastic.Clients.Elasticsearch

这里因为我自己搭的实验ES集群环境是7.x版本,所以我使用的实NEST,不过操作都是类似的。

在Infrastructure目录下,定义一个ElasticProxy用于获取Elastic的.NET客户端:

public interface IElasticProxy
{
IElasticClient GetClient(string indexName = null);
} public class ElasticProxy : IElasticProxy
{
private readonly string ElasticServerUrl;
private readonly string DefaultIndexName; public ElasticProxy(IConfiguration configuration)
{
ElasticServerUrl = configuration["Elastic:ServerUrl"] ?? throw new ArgumentNullException();
DefaultIndexName = configuration["Elastic:DefaultIndex"] ?? throw new ArgumentNullException();
} public IElasticClient GetClient(string indexName = null)
{
var settings = new ConnectionSettings(new Uri(ElasticServerUrl))
.DefaultIndex(indexName ?? DefaultIndexName);
return new ElasticClient(settings);
}
}

定义ElasticRepository基类

为了方便后续定义具体的Repository,我们这里先定义一个ElasticRepository的基类,帮我们把CRUD操作做一个基础的实现。

public interface IElasticRepositoryBase<T> where T : ElasticModelBase
{
Task AddAsync(T item);
Task UpdateAsync(T item);
Task DeleteAsync(string id);
Task<Tuple<int, IList<T>>> QueryAsync(int page, int limit);
} public abstract class ElasticRepositoryBase<T> : IElasticRepositoryBase<T> where T : ElasticModelBase
{
private readonly IElasticProxy _elasticProxy; public ElasticRepositoryBase(IElasticProxy elasticProxy)
{
_elasticProxy = elasticProxy;
} protected abstract string IndexName { get; }
protected IElasticClient Client => _elasticProxy.GetClient(IndexName); public virtual async Task AddAsync(T item)
{
await this.Client.IndexAsync(item, x => x.Index(this.IndexName));
} public virtual async Task DeleteAsync(string id)
{
await this.Client.DeleteAsync<T>(id, x => x.Index(this.IndexName));
} public virtual async Task UpdateAsync(T item)
{
await this.Client.UpdateAsync<T>(item.Id, x => x.Index(this.IndexName).Doc(item));
} public virtual async Task<Tuple<int, IList<T>>> QueryAsync(int page, int limit)
{
var query = await this.Client.SearchAsync<T>(x => x.Index(this.IndexName)
.From((page -1) * limit)
.Size(limit)); return new Tuple<int, IList<T>>(Convert.ToInt32(query.Total), query.Documents.ToList());
}
}

有了上面的基类,我们再去实现具体的Repository就方便的多啦。

实现AppLogRepository

下面我们可以很方便的实现一个AppLogRepository啦,是不是很方便!

public class AppLogRepository : ElasticRepositoryBase<AppLog>, IAppLogRepository
{
public AppLogRepository(IElasticProxy elasticProxy) : base(elasticProxy)
{
} protected override string IndexName => "app-logs";
}

定义依赖注入

下面我们把要用到的ElasticProxy和Repository注入到ServiceCollection中,后面Controller就可以用了!这里我们在Infrastructure中实现一个扩展方法,便于在Program.cs中使用。

public static class InfraServiceExtensions
{
public static void AddApplicationInfrastructure(this IServiceCollection services)
{
services.AddSingleton<IElasticProxy, ElasticProxy>();
services.AddSingleton<IProductRepository, ProductRepository>();
services.AddSingleton<IAppLogRepository, AppLogRepository>();
}
}

然后在Program.cs中使用这个扩展方法:

......
// Add infra services / repositories
builder.Services.AddApplicationInfrastructure();

实现AppLogController

下面我们就可以快速实现一个Controller来调用Repository实现ES的CRUD操作啦:

[ApiController]
[Route("[controller]")]
public class AppLogController : ControllerBase
{
private readonly IAppLogRepository _appLogRepository; public AppLogController(IAppLogRepository appLogRepository)
{
_appLogRepository = appLogRepository;
} [HttpGet]
public async Task<IActionResult> QueryAsync(int page = 1, int limit = 10)
{
var result = await _appLogRepository.QueryAsync(page, limit);
return Ok(new
{
total = result.Item1,
items = result.Item2
});
} [HttpPost]
public async Task<IActionResult> AddAsync([FromBody] AppLog log)
{
await _appLogRepository.AddAsync(log);
return Ok("Success");
} [HttpPut]
public async Task<IActionResult> UpdateAsync([FromBody] AppLog log)
{
await _appLogRepository.UpdateAsync(log);
return Ok("Success");
} [HttpDelete]
public async Task<IActionResult> DeleteAsync([Required] string id)
{
await _appLogRepository.DeleteAsync(id);
return Ok("Success");
}
}

快速测试

下面我们就可以打开Swagger来做一个测试啦:

通过Post方式创建一个applog,然后我们通过Get方式查询一下结果如下:

这时我们还可以通过在ES中通过Query DSL来验证一下:

GET app-logs/_search

查询结果如下图所示:

至于Put和Delete就留给你去验证吧。

小结

本篇,我们了解了如何在ASP.NET 6应用中集成ElasticSearch,并通过示例了解了如何做CRUD操作,并通过一定的封装提高了复用性。

下一篇我们了解下如何在ASP.NET 6应用对ES中的数据进行查询 和 聚合。

示例代码

Github:https://github.com/Coder-EdisonZhou/ElasticSamples

参考资料

博客园,包子wxl,《ElasticSearch使用系列-.NET6对接ES

CSDN,阿星Plus,《.NET Core下使用ES

CSDN,风神.NET,《如何在ASP.NET Core中集成ES

极客时间,阮一鸣,《ElasticSearch核心技术与实战

作者:周旭龙

出处:https://edisonchou.cnblogs.com

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

Elastic学习之旅 (11) .NET 6应用集成ES - 上的更多相关文章

  1. 笔记-JavaWeb学习之旅11

    请求转发:一种在服务器内部的资源跳转方式 使用步骤 1.通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path) ...

  2. Spring MVC学习总结(11)——Spring MVC集成Swagger跨域问题

      <!-- CORS配置,为了让别的机器访问本机的swagger接口文档服务 -->          <dependency>              <group ...

  3. WCF学习之旅—WCF服务的Windows 服务程序寄宿(十一)

    上接    WCF学习之旅—WCF服务部署到IIS7.5(九) WCF学习之旅—WCF服务部署到应用程序(十) 七 WCF服务的Windows 服务程序寄宿 这种方式的服务寄宿,和IIS一样有一个一样 ...

  4. WCF学习之旅—WCF第二个示例(五)

    二.WCF服务端应用程序 第一步,创建WCF服务应用程序项目 打开Visual Studio 2015,在菜单上点击文件—>新建—>项目—>WCF服务应用程序.在弹出界面的“名称”对 ...

  5. 180分钟的python学习之旅

    最近在很多地方都可以看到Python的身影,尤其在人工智能等科学领域,其丰富的科学计算等方面类库无比强大.很多身边的哥们也提到Python非常的简洁方便,比如用Django搭建一个见得网站只需要半天时 ...

  6. 开发了5年android,我开始了go学习之旅

    前言 做了近5年的android开发,最近项目也是不怎么忙,空闲的时候总会思考一些事情,不过作为移动开发,我个人觉得很有必要学习后台开发,由于公司是Go语言开发的,了解go语言一段时间后,我发现go语 ...

  7. SSIS 学习之旅 数据同步

    这一章 别人也有写过但是我觉得还是写写比较好.数据同步其实就是想仿照 数据库的发布订阅功能 第一章:SSIS 学习之旅 第一个SSIS 示例(一)(上) 第二章:SSIS 学习之旅 第一个SSIS 示 ...

  8. awk二十问-【AWK学习之旅】

    ---===AWK学习之旅===--- 一行命令: 1.打印输入每行的字段总数: 最后一行的字段总数:END{print NF} 每行都显示字段总数: {print NF}   2.打印指定行: aw ...

  9. awk十三问-【AWK学习之旅】

    ---===AWK学习之旅===--- 十三个常用命令行处理   [root@monitor awkdir]# cat emp.txt Beth 4.00 0 Dan 3.75 0 Kathy 4.0 ...

  10. awk分割列-【AWK学习之旅】

    ---===AWK学习之旅===--- awk 内置分割函数:split,将列按照指定分割符,分割成数组 用法:split(str1,array,"分隔符") 文件内容: [roo ...

随机推荐

  1. 3D Gaussian 三维视觉重建

    论文资料 论文 https://repo-sam.inria.fr/fungraph/3d-gaussian-splatting/3d_gaussian_splatting_low.pdf 资料网站 ...

  2. SpringAI用嵌入模型操作向量数据库!

    嵌入模型(Embedding Model)和向量数据库(Vector Database/Vector Store)是一对亲密无间的合作伙伴,也是 AI 技术栈中紧密关联的两大核心组件,两者的协同作用构 ...

  3. zk基础—3.集群与核心参数

    大纲 1.zk单机模式是如何启动的 2.zk集群是如何部署和启动的 3.zk集群部署要用什么样配置的机器 4.如何合理设置zk的JVM参数以及内存大小 5.zk配置的核心参数之tickTime.dat ...

  4. System V信号量 vs. POSIX信号量:核心区别与选型指南

    System V信号量 vs. POSIX信号量:核心区别与选型指南 最近在学习linux系统编程的章节,接触到了两种信号量,所以专门研究了二者的区别,将二者的对比记录于此. 在Linux多线程/进程 ...

  5. RL · Exploration | 使用时序距离构造 intrinsic reward,鼓励 agent 探索

    论文标题:Episodic Novelty Through Temporal Distance. ICLR 2025,8 8 6 5 poster. arxiv:https://arxiv.org/a ...

  6. Spring的基础结构和核心接口

    目录 1.BeanDefinition 2.BeanDefinitionReader 3.BeanDefinitionRegistry 4.BeanFactory 5.ApplicationConte ...

  7. c#几种场景获取程序运行目录

    控制台.app等桌面应用程序(兼容系统自启) 1 System.IO.Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.File ...

  8. PHP获取下个月今天时间

    获取php下个月当前时间public static function fq_time($time = ""){ if (!$time) $time = time(); $arr = ...

  9. tar命令打包指定目录及其文件,而不包括其上级目录

    想指定将/var目录下的log目录及其文件打包到当前目录,在压缩包解压时不包括/var目录,可使用如下方式: tar -zcvf log_bak.tar.gz -C /var/ log # 注意log ...

  10. AD系列:Windows Server 2025 搭建AD域控和初始化

    简介 本教程主要内容为使用Windows Server 2025 部署Active Directory (ADDS\域控制器)服务. 所有操作尽量使用PowerShell,可提高部署效率和自动化操作. ...