EasyCore.Elasticsearch
8.3.0
dotnet add package EasyCore.Elasticsearch --version 8.3.0
NuGet\Install-Package EasyCore.Elasticsearch -Version 8.3.0
<PackageReference Include="EasyCore.Elasticsearch" Version="8.3.0" />
<PackageVersion Include="EasyCore.Elasticsearch" Version="8.3.0" />
<PackageReference Include="EasyCore.Elasticsearch" />
paket add EasyCore.Elasticsearch --version 8.3.0
#r "nuget: EasyCore.Elasticsearch, 8.3.0"
#:package EasyCore.Elasticsearch@8.3.0
#addin nuget:?package=EasyCore.Elasticsearch&version=8.3.0
#tool nuget:?package=EasyCore.Elasticsearch&version=8.3.0
🔎 EasyCore.Elasticsearch
EasyCore.Elasticsearch 是面向 .NET 8 的通用 Elasticsearch 集成库。基于官方 Elastic.Clients.Elasticsearch,一键完成客户端 DI、索引管理、文档仓储与健康检查。
<p align="center"> <img src="https://raw.githubusercontent.com/RockyWang0521/EasyCore.Elasticsearch/master/png/EasyCoreLogo.png" alt="EasyCore Logo" width="120" /> </p>
🌍 Language
- 中文(当前文档)
- English: README.en.md
源码:github.com/RockyWang0521/EasyCore.Elasticsearch
📚 目录
第一部分:总览
第二部分:快速上手
第三部分:能力与 Demo
1. 🎯 项目定位
EasyCore.Elasticsearch 解决「在 ASP.NET Core 里一键接好 Elasticsearch,而不是手写一长串客户端与仓储样板代码」的问题:
| 痛点 | EasyCore.Elasticsearch 做法 |
|---|---|
手写 ElasticsearchClient 注册 |
AddEasyCoreElasticsearch(...) 一次注册 |
| 索引 / 模板 / 别名分散 | IElasticsearchIndexManager 统一管理 |
| CRUD + 搜索样板多 | IElasticsearchRepository<T> 通用仓储 |
| 缺少健康探测 | AddHealthChecks().AddEasyCoreElasticsearch() |
| 多节点 / 鉴权配置散落 | ElasticsearchOptions 统一配置 |
1.1 设计原则
| 原则 | 说明 |
|---|---|
| 低摩擦接入 | 一个扩展方法 + 一节配置即可跑通 |
| 官方客户端 | 基于 Elastic.Clients.Elasticsearch 8.17.3 |
| 职责清晰 | 客户端工厂 / 索引管理 / 文档仓储 / 健康检查分层 |
| 本地可联调 | README 给出 Docker Compose 与 Demo 步骤 |
| 审计另册 | 本包不包含审计概念;审计请使用 EasyCore.Audit |
2. 📁 仓库结构
EasyCore.Elasticsearch/
├── src/EasyCore.Elasticsearch/
│ ├── Client/ # 客户端工厂与响应映射
│ ├── DependencyInjection/ # AddEasyCoreElasticsearch 扩展
│ ├── Health/ # 健康检查
│ ├── Indexing/ # 索引 / 模板 / 别名
│ ├── Models/ # 搜索请求与结果模型
│ ├── Options/ # Options + Validator
│ └── Repository/ # 通用文档仓储
├── demo/
│ ├── docker-compose.yml # 单节点 ES(easycore-es-demo)
│ └── Web.EasyCore.Elasticsearch/
├── tests/EasyCore.Elasticsearch.Tests/
├── png/EasyCoreLogo.png
├── README.md
└── README.en.md
3. 📦 安装
dotnet add package EasyCore.Elasticsearch
需要 .NET 8。底层依赖 Elastic.Clients.Elasticsearch 8.17.3(面向 Elasticsearch 8.x)。
本地可用 Docker Compose 拉起单节点 Elasticsearch(见 Demo)。
4. ⚡ 三分钟快速开始
4.1 代码注册
using EasyCore.Elasticsearch;
builder.Services.AddEasyCoreElasticsearch(options =>
{
options.Nodes = ["http://localhost:9200"];
options.DefaultIndex = "demo-products";
options.RequestTimeout = TimeSpan.FromSeconds(30);
options.MaxRetryCount = 3;
// 可选 Basic Auth(ApiKey 优先):
// options.Username = "elastic";
// options.Password = "***";
// options.ApiKey = "***";
});
builder.Services.AddHealthChecks()
.AddEasyCoreElasticsearch();
注意:DI 扩展方法名为
AddEasyCoreElasticsearch,不是AddEasyCoreElasticsearch。
4.2 配置节示例
{
"Elasticsearch": {
"Nodes": [ "http://localhost:9200" ],
"DefaultIndex": "demo-products",
"RequestTimeoutSeconds": 30,
"MaxRetryCount": 3,
"EnableCertificateValidation": true
}
}
var section = builder.Configuration.GetSection("Elasticsearch");
builder.Services.AddEasyCoreElasticsearch(options =>
{
options.Nodes = section.GetSection("Nodes").Get<string[]>()?.ToList()
?? ["http://localhost:9200"];
options.DefaultIndex = section["DefaultIndex"] ?? "demo-products";
options.Username = section["Username"];
options.Password = section["Password"];
options.ApiKey = section["ApiKey"];
});
4.3 注入使用
public sealed class ProductService
{
private readonly IElasticsearchRepository<ProductDocument> _repository;
private readonly IElasticsearchIndexManager _indexes;
public ProductService(
IElasticsearchRepository<ProductDocument> repository,
IElasticsearchIndexManager indexes)
{
_repository = repository;
_indexes = indexes;
}
public async Task IndexAsync(ProductDocument doc, CancellationToken ct)
{
if (!await _indexes.IndexExistsAsync("demo-products", ct))
{
await _indexes.CreateIndexAsync("demo-products", cancellationToken: ct);
}
await _repository.IndexAsync(doc, "demo-products", doc.Id, ct);
}
public Task<ElasticsearchSearchResult<ProductDocument>> SearchAsync(
string? q, string? category, int pageIndex = 0, int pageSize = 20, CancellationToken ct = default)
{
var request = new ElasticsearchSearchRequest
{
Query = q,
PageIndex = pageIndex < 0 ? 0 : pageIndex,
PageSize = pageSize <= 0 ? 20 : pageSize,
SortField = "createdAt",
SortDescending = true,
// text 字段的 Term 过滤请使用 .keyword 子字段
Filters = string.IsNullOrWhiteSpace(category)
? null
: new Dictionary<string, object?> { ["category.keyword"] = category }
};
return _repository.SearchAsync(request, "demo-products", ct);
}
}
5. ⚙️ 配置项
| 键 | 说明 | 默认 |
|---|---|---|
Nodes |
ES 节点 URL 列表(至少一个) | [](必填) |
Username / Password |
Basic Auth(有 ApiKey 时忽略) |
null |
ApiKey |
API Key(优先于用户名密码) | null |
DefaultIndex |
调用方未指定索引时的默认索引 | null |
RequestTimeout |
请求超时 | 30s |
MaxRetryCount |
传输层最大重试次数 | 3 |
EnableCertificateValidation |
是否校验 SSL 证书 | true |
EnableDebugMode |
Elastic 调试模式 | false |
EnableRequestResponseLogging |
请求/响应日志(不记录凭据) | false |
DefaultNumberOfShards |
建索引默认分片数 | 1 |
DefaultNumberOfReplicas |
建索引默认副本数 | 0 |
配置节名:Elasticsearch(ElasticsearchOptions.SectionName)。
6. 🧩 核心能力
6.1 客户端与 DI
AddEasyCoreElasticsearch(Action<ElasticsearchOptions>):注册ElasticsearchClient、IElasticsearchIndexManager、IElasticsearchRepository<>,并启用 Options 校验- 多次调用安全:后续调用仅更新 Options,不会重复注册核心服务
6.2 索引管理(IElasticsearchIndexManager)
| 方法 | 说明 |
|---|---|
IndexExistsAsync / CreateIndexAsync / DeleteIndexAsync |
索引生命周期 |
CreateOrUpdateTemplateAsync / TemplateExistsAsync |
索引模板 |
CreateAliasAsync / AliasExistsAsync |
别名 |
RefreshIndexAsync |
刷新索引 |
6.3 文档仓储(IElasticsearchRepository<T>)
| 方法 | 说明 |
|---|---|
IndexAsync / IndexManyAsync / BulkAsync |
写入 / 批量写入 |
GetAsync / ExistsAsync |
按 Id 读取 / 判断存在 |
UpdateAsync |
部分更新 |
DeleteAsync / DeleteManyAsync |
删除 |
SearchAsync / CountAsync |
搜索与计数 |
6.4 搜索约定
| 约定 | 说明 |
|---|---|
PageIndex |
从 0 开始 |
PageSize |
默认 20;≤ 0 时建议回退为 20 |
Filters |
Term 过滤;对 text 映射字段请使用 field.keyword(如 category.keyword) |
Query |
可选全文检索(全字段) |
SortField / SortDescending |
排序字段与方向 |
6.5 健康检查
builder.Services.AddHealthChecks()
.AddEasyCoreElasticsearch(); // 默认 name = "elasticsearch"
app.MapHealthChecks("/health");
6.6 与审计的关系
本包不包含审计写入、审计查询或审计中间件。若需要操作审计,请使用独立包 EasyCore.Audit。
7. 🧪 Demo
7.1 🐳 启动 Elasticsearch
docker compose -f demo/docker-compose.yml up -d
| 项 | 值 |
|---|---|
| 容器名 | easycore-es-demo |
| 镜像 | elasticsearch:8.15.0(单节点,安全关闭) |
| 端口 | 9200 |
停止 / 再开:docker compose -f demo/docker-compose.yml down / up -d。
7.2 🚀 运行 Demo
dotnet run --project demo/Web.EasyCore.Elasticsearch
| 端点 | 说明 |
|---|---|
| http://localhost:5089/swagger | Swagger |
GET /health |
ES 健康检查 |
POST /api/indexes/{indexName} |
创建索引 |
POST /api/products |
写入文档 |
POST /api/products/bulk |
批量写入 |
GET /api/products?q=&category=&pageIndex=0&pageSize=20 |
搜索(category 走 category.keyword) |
GET /api/products/{id} |
按 Id 读取 |
PUT /api/products/{id} |
更新 |
DELETE /api/products/{id} |
删除 |
GET /api/products/count |
计数 |
顺序:先起 easycore-es-demo(9200 通)→ 再跑 Demo → 再调 API。
7.3 示例请求
# 创建索引
curl -X POST http://localhost:5089/api/indexes/demo-products
# 写入
curl -X POST http://localhost:5089/api/products -H "Content-Type: application/json" -d "{\"name\":\"Keyboard\",\"category\":\"peripherals\",\"price\":99.5}"
# 搜索(category Term 过滤)
curl "http://localhost:5089/api/products?category=peripherals&pageIndex=0&pageSize=20"
8. ❓ FAQ
Q: 扩展方法叫什么?
A: AddEasyCoreElasticsearch。不要写成 AddEasyCoreElasticsearch。
Q: 按 category 过滤为什么查不到?
A: 动态映射下 category 多为 text。Term 过滤请使用 category.keyword。
Q: pageIndex / pageSize 默认是多少?
A: PageIndex 从 0 开始;PageSize 默认 20。Demo API 在 pageSize <= 0 时回退为 20。
Q: 本包是否自带审计?
A: 不包含。审计请使用 EasyCore.Audit。
Q: 健康检查怎么挂?
A: builder.Services.AddHealthChecks().AddEasyCoreElasticsearch();,再 MapHealthChecks("/health")。
Q: 需要 Elasticsearch 几?
A: 面向 8.x;客户端包版本为 Elastic.Clients.Elasticsearch 8.17.3。
9. 📄 License
MIT
🤝 贡献
- Fork 并创建特性分支
- 在
tests/EasyCore.Elasticsearch.Tests补充测试 - 执行
dotnet test与dotnet build - 提交 Pull Request
欢迎 Issue / PR 🚀
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Elastic.Clients.Elasticsearch (>= 8.17.3)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.2)
- Microsoft.Extensions.Diagnostics.HealthChecks (>= 8.0.11)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.2)
- Microsoft.Extensions.Options (>= 8.0.2)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 8.0.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on EasyCore.Elasticsearch:
| Package | Downloads |
|---|---|
|
EasyCore.Audit
Automatic HTTP audit logging for ASP.NET Core with pluggable stores (Elasticsearch, file, database, custom). |
GitHub repositories
This package is not used by any popular GitHub repositories.