ElasticSearch NEST操作(3)详细介绍

news/2025/2/3 18:33:13/文章来源:https://www.cnblogs.com/tangge/p/18697617

NEST 是 Elasticsearch 的官方高级 .NET 客户端,提供了强类型的 DSL(领域特定语言)来与 Elasticsearch 交互。以下是 NEST 中常用的核心类及其用途,按功能分类整理:


1. 客户端与连接类

  • ElasticClient
    所有操作的入口类,用于执行索引、搜索、更新、删除等操作。

    var settings = new ConnectionSettings(new Uri("http://localhost:9200"));
    var client = new ElasticClient(settings);
    
  • ConnectionSettings
    配置 Elasticsearch 连接参数(如节点地址、认证、超时时间等)。

    var settings = new ConnectionSettings(new Uri("http://localhost:9200")).DefaultIndex("my-index");
    

2. 索引管理类

1. CreateIndexDescriptor(索引创建描述符)

用于定义索引的映射、设置(如分片数、副本数)。

方法 作用
.AutoMap<T>() 根据类 T 的属性自动推断字段类型
.NumberOfShards 主分片数量(创建后不可修改)
.NumberOfReplicas 副本数量(可动态调整)
.Analysis 配置自定义分词器、过滤器和 tokenizer
var createIndexResponse = client.Indices.Create("my-index", c => c.Map<MyDocument>(m => m.AutoMap()).Settings(s => s.NumberOfShards(3))
);

更详细:

var createResponse = client.Indices.Create("products", c => c// 1. 映射配置.Map<Product>(m => m.AutoMap()  // 自动映射 Product 类的属性.Properties(p => p.Text(t => t.Name(n => n.Name).Analyzer("ik_max_word")) // 指定分词器.Number(n => n.Name(n => n.Price).Type(NumberType.Double)) // 明确指定数值类型.Date(d => d.Name(n => n.CreatedAt).Format("yyyy-MM-dd")) // 自定义日期格式))// 2. 索引设置.Settings(s => s.NumberOfShards(3)        // 主分片数.NumberOfReplicas(1)      // 副本数.Analysis(a => a          // 自定义分析器.Analyzers(an => an.Custom("my_analyzer", ca => ca.Tokenizer("standard").Filters("lowercase", "asciifolding")))))
);

2. IndexSettingsDescriptor(索引设置描述符)

配置索引的分词器、分析器等设置。

专门用于配置索引的高级设置,如分词器、存储优化等。

常见配置场景

  • 自定义分析器:定义复杂的分词规则。
  • 静态配置:如 refresh_interval 控制索引刷新频率。
  • 合并策略:优化段合并行为。

示例

var updateSettingsResponse = client.Indices.UpdateSettings("logs", s => s.Settings(settings => settings.Analysis(a => a.TokenFilters(tf => tf.Synonym("my_synonyms", sf => sf.SynonymsPath("analysis/synonym.txt") // 从文件加载同义词)).Analyzers(an => an.Custom("my_custom_analyzer", ca => ca.Tokenizer("whitespace").Filters("lowercase", "my_synonyms")))).RefreshInterval("30s")          // 每30秒刷新一次索引.Merge(m => m.Policy(p => p.SegmentsPerTier(24)     // 控制段合并策略)))
);

关键参数说明

配置项 作用
.Analysis 定义分词器、过滤器(如同义词、停用词)
.RefreshInterval 索引刷新间隔(影响近实时搜索性能)
.Merge.Policy 控制 Lucene 段合并策略,优化写入性能

3. 其他常见索引操作

删除索引

var deleteResponse = client.Indices.Delete("old_index");

获取索引信息

var getResponse = client.Indices.Get("products");
var settings = getResponse.Indices["products"].Settings;

关闭/打开索引

// 关闭索引(禁止写入/搜索)
client.Indices.Close("products");// 打开索引
client.Indices.Open("products");

别名管理

client.Indices.PutAlias("products", "current_products");

最佳实践建议

  1. 分片数量:根据数据量和硬件资源合理设置(通常单个分片 10-50GB)。
  2. 副本数量:生产环境至少 1 个副本,保障高可用。
  3. 动态映射:通过 dynamic: strict 避免字段自动映射导致污染。
  4. 分析器测试:使用 Analyze API 提前验证分词效果。

通过合理使用索引管理 API,可以显著优化 Elasticsearch 的写入性能、查询效率和资源利用率。


3. 文档操作类

1 IndexRequest<T>IndexDescriptor<T> 核心功能

用于向 Elasticsearch 索引(插入或更新)单个文档

  • 插入新文档:若文档 ID 不存在,直接创建新文档。
  • 更新文档:若文档 ID 已存在,默认会覆盖旧文档(类似 PUT 操作)。
  • 自动映射:文档字段类型根据 T 类的属性自动推断(需提前创建索引或启用动态映射)。

基础用法示例

1. 直接索引文档(自动处理 ID)

使用 IndexDocument 快捷方法,自动从对象中提取 Id 属性作为文档 ID

var document = new MyDocument 
{ Id = 1, Name = "Test Document",Timestamp = DateTime.UtcNow
};// 自动使用 document.Id 作为文档 ID
var response = client.IndexDocument(document);

HTTP 请求

POST /my-index/_doc/1 HTTP/1.1
Host: localhost:9200
Content-Type: application/json
Accept: application/json{"id": 1,"name": "Test Document","timestamp": "2023-10-05T12:34:56.789Z"
}
2. 显式指定操作参数

使用 Index 方法并通过 IndexDescriptor<T> 精细控制索引行为

var response = client.Index(new IndexRequest<MyDocument>(document)
{Index = "my-index",      // 指定目标索引名称Id = document.Id,        // 显式设置文档 IDRouting = "user-123",    // 按用户ID路由分片Refresh = Refresh.True,  // 操作后立即刷新索引(确保实时可见)Version = 5              // 乐观并发控制(仅当文档版本为5时更新)
});

关键参数详解

通过 IndexDescriptor<T> 可配置以下核心参数:

方法/参数 说明
.Id(id) 手动指定文档 ID(默认从对象的 Id 属性获取)
.Index("index-name") 指定文档存储的索引名称(若未设置,使用类名小写化,如 mydocument
.Routing("route-key") 设置路由键,控制文档存储在哪个分片
.Version(version) 乐观锁控制,仅当文档当前版本匹配时更新
.Refresh(Refresh.True) 操作后立即刷新索引(默认false,若需实时查询需开启,但影响性能)
.Timeout("30s") 等待分片响应的超时时间(防止长时间阻塞)
.OpType(OpType.Create) 强制仅创建文档(若ID已存在则失败,避免覆盖)
.Pipeline("my-pipeline") 指定预处理管道(如数据转换、字段增强)

高级用法场景

1. 条件索引(避免覆盖)

使用 OpType.Create 强制仅创建新文档,若 ID 存在则抛出异常:

var response = client.Index(document, i => i.Id(document.Id).OpType(OpType.Create)  // 类似于 PUT with _create
);
2. 乐观并发控制

通过版本号或时间戳确保并发更新安全:

// 使用版本号控制
var response = client.Index(document, i => i.Version(document.Version) // 文档当前版本号(从ES读取时获取).VersionType(VersionType.External) // 版本由外部系统管理
);// 使用时间戳控制
var response = client.Index(document, i => i.IfSequenceNumber(10)   // 仅当序列号匹配时更新.IfPrimaryTerm(2)
);
3. 动态索引名称

根据数据内容动态选择索引(如按时间分片):

string monthlyIndex = $"logs-{DateTime.UtcNow:yyyy-MM}";
var response = client.Index(document, i => i.Index(monthlyIndex)
);

最佳实践建议

  1. ID 生成策略

    • 业务ID:若文档有唯一业务标识(如订单号),优先手动指定 Id
    • 自动生成:无业务ID时,可省略 Id,Elasticsearch 会自动生成唯一 ID(GUID)。
  2. 路由优化

    • 对高频查询场景,通过 Routing 将相同路由键的文档存于同一分片,提升查询效率。
  3. 性能调优

    • 避免频繁刷新:批量导入时设置 Refresh(false) 减少刷新开销。
    • 合理分片:根据数据规模设计分片数,避免单个分片过大(推荐 10-50GB)。
  4. 错误处理

    • 捕获 ElasticsearchClientException 处理版本冲突、索引不存在等异常。
    • 使用重试机制应对网络波动或临时故障。

完整示例

var document = new Product 
{Id = "p-100",Name = "Elasticsearch Guide",Price = 45.99,Category = "books"
};var indexResponse = client.Index(document, i => i.Index("products").Id(document.Id).Routing(document.Category)  // 按分类路由分片.Timeout("10s").Refresh(Refresh.WaitFor)    // 等待刷新完成后再返回.Pipeline("product-enricher") // 通过管道处理数据
);if (indexResponse.IsValid)
{Console.WriteLine($"文档索引成功!版本:{indexResponse.Version}");
}
else
{Console.WriteLine($"错误:{indexResponse.DebugInformation}");
}

通过 IndexRequest<T>IndexDescriptor<T>,开发者可以灵活控制文档的索引行为,结合 Elasticsearch 的版本控制、路由策略和性能优化选项,构建高效可靠的数据写入逻辑。

2 BulkDescriptor

批量操作(索引、更新、删除)的容器。

client.Bulk(b => b.Index("my-index").IndexMany(documents)
);

3 UpdateRequest<T> / UpdateDescriptor<T>

更新文档内容或脚本操作。


4. 查询与过滤类

  • QueryContainer / QueryContainerDescriptor<T>
    构建查询条件(如 termmatchbool 查询)。

    var searchResponse = client.Search<MyDocument>(s => s.Query(q => q.Match(m => m.Field(f => f.Name).Query("test")))
    );
    
  • SearchRequest<T> / SearchDescriptor<T>
    定义搜索请求的参数(分页、排序、高亮等)。

  • BoolQuery
    组合多个查询条件(mustshouldmust_not)。


5. 聚合类

  • AggregationContainer / AggregationContainerDescriptor<T>
    构建聚合分析(如 termsdate_histogram)。

    var response = client.Search<MyDocument>(s => s.Aggregations(a => a.Terms("group_by_field", t => t.Field(f => f.Category)))
    );
    
  • TermsAggregation / DateHistogramAggregation
    具体聚合类型的实现。


6. 响应类

  • ISearchResponse<T>
    搜索操作的响应结果,包含文档和聚合数据。

    var documents = searchResponse.Documents; // 获取匹配的文档
    var termsAgg = searchResponse.Aggregations.Terms("group_by_field");
    
  • IndexResponse / BulkResponse
    单个文档索引或批量操作的响应结果。


7. 映射与类型类

  • TypeMappingDescriptor<T>
    定义索引的字段映射(类型、分词器、是否存储等)。

    client.Indices.Create("my-index", c => c.Map<MyDocument>(m => m.AutoMap() // 自动映射.Properties(p => p.Text(t => t.Name(n => n.Name).Analyzer("standard"))))
    );
    
  • 属性注解
    通过属性标记字段映射(如 [Text(Name = "field_name")])。


8. 辅助工具类

  • Id
    表示文档的唯一标识,支持多种类型(如 stringint)。

    var id = new Id(document);
    
  • Routing
    指定文档的路由值。

  • Nest.JsonNetSerializer
    集成 JSON.NET 序列化器,支持自定义序列化逻辑。


9. 异步操作

所有方法均有异步版本(如 SearchAsyncIndexAsync),支持 async/await


示例场景

创建索引并索引文档

var client = new ElasticClient(new ConnectionSettings(new Uri("http://localhost:9200")));// 创建索引
client.Indices.Create("my-index", c => c.Map<MyDocument>(m => m.AutoMap())
);// 索引文档
var document = new MyDocument { Id = 1, Name = "Example" };
client.IndexDocument(document);

执行复杂搜索

var response = client.Search<MyDocument>(s => s.Query(q => q.Bool(b => b.Must(mu => mu.Match(m => m.Field(f => f.Name).Query("test"))))).Aggregations(a => a.DateHistogram("by_month", dh => dh.Field(f => f.Date).CalendarInterval(DateInterval.Month)))
);

以上是 NEST 中常用的核心类,覆盖了索引管理、文档操作、搜索、聚合等主要功能。具体使用时需结合 Elasticsearch 的版本和 NEST 的文档调整语法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/878341.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

为什么选择持续绩效管理(CPM)

组织变革和发展的关键始于你的员工基础。要想在组织中建立一个不断发展和创新的环境,你必须确保你的员工是以目标、绩效和反馈为导向的。 #持续绩效管理#鼓励上级和下级之间建立直接的双向沟通。一个持续的绩效评估可以确保平稳有效的联系,随着时间的推移,可以看到更好的结果…

unity直接安装插件

一共三步 1.窗口->包管理器2. 在弹出的界面里点左上角的加号 依次解读选项为disk 文件夹(zip压缩文件请提前解压)tarball 压缩包(只支持tar压缩包)git URL 网址下载(国内应该得设置代理)by name 指定软件和版本下载 3.以disk为例,进入解压的地方选中package.json接着…

北航计网课程笔记-四、网络层

第四章 网络层 本章重点 1、IP数据报的格式和分片 2、IP地址的表示和分类分配、子网掩码、地址有效性、广播地址 3、子网划分 4、CIDR路由聚合 5、ARP协议和ICMP协议 6、路由表、路由器的工作原理 7、RIP协议和OSPF协议 8、网络层的综合设计和应用 网络层的功能 网络层的主要任…

北航计网课程笔记-六、应用层

第六章 应用层 应用层概述 应用层对应用程序的通信提供服务。应用层的功能:文件传输、访问和管理 电子邮件 虚拟终端 查询服务和远程作业登录应用层的重要协议FTP SMTP、POP3 HTTP DNS网络应用模型 客户/服务器模型C/S客户是服务请求方,服务器是服务提供方 Web、FTP、远程登录…

北航计网课程笔记-七、一些总结

复习到最后想开摆了,也没总结啥,只是一些格式……一些总结MAC帧格式IP数据报格式 IP首部20B~60B IP总长最多65535BTCP报文格式 TCP首部20B~60B 数据部分最多65535-20-20 = 65495BUDP报文格式UDP&TCP伪首部格式HTTP报文格式

北航计网课程笔记-一、概述

写在前面:本笔记根据王道408完成,北航软院不考的内容不在其中。 总之复习期末把王道刷一遍就行了。 个人学习用,如有错误敬请指正。第一章 概述 计算机网络概念 计算机网络的定义:一些互联的、自治的计算机的集合,主体是多台计算机,媒介为通信媒介, 目的是通信与资源共享…

北航计网课程笔记-二、物理层

第二章 物理层 物理层的任务:将原始的比特流从一台机器上传输到另一台机器上。 确定与传输媒体的接口特性:机械、电气、功能、规程通信基础 一些基本概念数据,信号和码元数据是传送信息的实体;信号是数据的电气或电磁表现;码元是数字通信中数字信号的计量单位,1码元可以携…

Winform和MFC的一个区别

前段时间我嫌桌面快捷键太多,我使用C语言用MFC制作了桌面自定义系统(上图左),可是这个系统存在一些问题,比如(下图) 默认情况下它的右上角没有最大化和最小化的按钮,而Winform是有的(下图)。 还有一个问题:在任务栏,点击时MFC不能最小化,而Winform可以;还有一个很…

应用中的 PostgreSQL项目案例

title: 应用中的 PostgreSQL项目案例 date: 2025/2/3 updated: 2025/2/3 author: cmdragon excerpt: 随着大数据和云计算的兴起,企业在数据管理和数据分析方面面临着越来越复杂的挑战。PostgreSQL 作为一个开源关系型数据库,凭借其卓越的扩展性和强大的功能,逐渐成为众多企业…

来自aakennes的新年祝福

来自aakennes的新年祝福组题人: @aakennes \(A\) P888. 字符串会上树 \(AC\)基础字符串。点击查看代码 string s,t="",w=""; map<string,string>f; int main() { // #define Isaac #ifdef Isaacfreopen("in.in","r",stdin);fr…

1.3 决定程序流程的程序计数器

CPU先执行0100 CPU每执行一个指令,程序计数器的值就会自动加1 CPU的控制器就会参照程序计数器的数值,从内存中读取命令并执行。 程序计数器决定着程序的流程

【每日一题】20250203

你是万千星球的星球! 你是沸腾的准则!你是精心保存的潜伏的萌芽!你是核心!【每日一题】我国发射的“天宫一号”和“神州八号”在对接前,”天宫一号”的运行轨道高度为 \(350 \; \mathrm{km}\),“神州八号”的运行轨道高度为 \(343 \; \mathrm{km}\).它们的运行轨道均视为…