Elasticsearch.Nest 教程系列 1:Nest 快速入门
本系列博文是“伪”官方文档翻译(更加本土化),并非完全将官方文档进行翻译,而是在查阅、测试原始文档并转换为自己真知灼见后的“准”翻译。有不同见解 / 说明不周的地方,还请海涵、不吝拍砖 :)
官方文档见此:https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/introduction.html
本系列对应的版本环境:ElasticSearch@7.3.1,NEST@7.3.1,IDE 和开发平台默认为 VS2019,.NET CORE 2.1
Elasticsearch.Net 和 NEST 对比说明:
-
Elasticsearch 官方为 .NET 提供了 2 个官方客户端库:Elasticsearch.Net 和 NEST。
-
可以简单理解为 Elasticsearch.Net 是 NEST 的一个子集。
-
NEST 内部使用了 ElasticSearch.Net ,并通过 NEST 可以对外暴露 ElasticSearch.Net 客户端。
-
但 NEST 包含了 ElasticSearch.Net 所没有的一些高级功能,如:
- 强类型查询 DSL:可以将所有请求和响应的对象类型转换 1:1 的.NET 类型。
- 自动转换为 CLR 的数据类型。
基本上 .NET 项目到了要使用上 ElasticSearch 的地步,直接选择 NEST 即可。
在使用 NEST 作为客户端的时候,建议将 ElasticClient 对象作为单例来使用。
-
ElasticClient 被设计为线程安全。
-
ES 中的缓存是根据 ConnectionSettings 来划分的,即服务端缓存针对的是每一个 ConnectionStrings
-
例外: 当你需要连接不同的 ES 集群的时候,就不要用单例了,应为不同的 ElasticClient 使用不同的 ConnectionStrings。
快速使用
使用 Nest 的时候约定 Nest 版本需要跟 ElasticSearch 版本保持一致,即服务端 ES版本为 7.3.1,则 Nest 版本也要使用 7.3.1
以下示例通过 IoC 进行注入(单例),你也可以直接通过单例模式来实现。
配置、连接 ElasticSearch
配置类:
1 | public class ElasticSearchSettings |
ElasticSearch 客户端:
-
连接到 ElasticSearch,并设定默认索引
1 | public class ElasticSearchClient : IElasticSearchRepository |
-
建议增加默认索引名,不然在请求时推断索引名的时候可能会引发异常,更多关于索引名的推断见此博文NEST 教程系列 9-1 转换:Index name inference | 索引名推断的3种方式
连接配置上使用密码凭证
ElasticSearch 可以直接在 Uri 上指定密码,如下:
1 | var uri = new Uri("http://username:password@localhost:9200") |
-
但不建议这么做,尤其是在多个节点的连接池或者能够 reseeding 的连接池上的时候。
-
**建议使用 ConnectionSettings 来设定凭证。NEST 教程系列 2-4 连接:Working with certificates | 使用凭证连接
使用连接池
ConnectionSettings 不仅支持单地址的连接方式,同样提供了不同类型的连接池来让你配置客户端,如使用 SniffingConnectionPool 来连接集群中的 3 个 Elasticsearch 节点,客户端将使用该类型的连接池来维护集群中的可用节点列表,并会以循环的方式发送调用请求。
1 | var uris = new[]{ |
NEST 教程系列 2-1 连接:Configuration options| 配置选项
索引(Indexing)
-
这里的“索引”需理解为动词,用 indexing 来理解会更好,表示将一份文档插入到 ES 中。
假设有如下类 User.cs
1 | public class User |
索引(Indexing)/添加 一份文档到 ES 中
1 | //同步 |
-
目前提供的方法基本上都含有同步和异步版本(异步方法以 *Async 结尾)
-
IndexDocument 方法会判断添加的文档是否已经存在(根据 _id),若存在,则添加失败。
-
NEST 会自动将 Id 属性作为 ES 中的 _id,更多关于 id 的推断方式见此博文:NEST 教程系列 9-3 转换:Id 推断
- 默认情况下,会使用 camel 命名方式进行转换,你可以使用 ConnectionSettings 对象的 .DefaultFieldNameInferrer(Func<string, string>) 方法来调整默认转换行为,更多关于属性的推断的见此博文:NEST 教程系列 9-4 转换:Field 属性推断
最终请求地址为:
1 | PUT /users/_doc/3a351ea1-bfc3-43df-ae12-9c89e22af144 |
查询
通过类 lambda 表达式进行查询
通过 Search
1 | var result = _client.Search<User>(s=>s.From(0) |
请求 URL 如下:
1 | POST /users/_search?typed_keys=true |
-
以上搜索是基于“users”索引来进行搜寻
如何在 ES 上的所有索引上进行搜索?通过 AllIndices(),如下:
1 | var result = _client.Search<User>(s=>s |
假设有如下文档:
1 | //users 索引 |
则最终可以获取到 users 和 thirdusers 索引中分别获取到 _id 为 3a351ea1-bfc3-43df-ae12-9c89e22af144 和 619ad5f8-c918-46ef-82a8-82a724ca5443 的文档信息。
可以通过 .AllTypes() 和 .AllIndices() 从所有 类型(types) 和 所有 索引(index)中查询数据,最终查询会生成在 /_search 请求中。关于 Type 和 Index,可分别参考:NEST 教程系列 9-6 转换:Document Paths 文档路径和跳转:NEST 教程系列 9-7 转换:Indices Paths 索引路径
通过查询对象进行查询
通过 SearchRequest 对象进行查询。
例:在所有索引查询 LastName="l1"的文档信息
1 | var request = new SearchRequest(Nest.Indices.All) //在所有索引上查询 |
生成的请求 URL 为:
1 | POST /_all/_search?typed_keys=true |
通过 .LowLever 属性来使用 Elasticsearch.Net 来进行查询
使用 Elasticsearch.Net 来进行查询的契机:
-
当客户端存在 bug,即使用上述 NEST 的 Search 和 SearchRequest 异常的时候,可以考虑用 Elasticsearch.Net 提供的查询方式。
-
当你希望用一个匿名对象或者 JSON 字符串来进行查询的时候。
1 | var response = _client.LowLevel.Search<SearchResponse<User>>("users", PostData.Serializable(new |
聚合查询
除了结构化和非结构化查询之外, ES 同样支持聚合(Aggregations)查询:
1 | var result = _client.Search<User>(s => s |
-
一般使用 term 聚合来获取每个存储桶的文档数量,其中每个桶将以 lastName 作为关键字。
更多关于聚合的操作可见此:NEST 教程系列 8 聚合:Writing aggregations | 使用聚合