Elastcisearch.Nest 7.x 系列`伪`官方翻译:通过 NEST 来快捷试用 Elasticsearch



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

配置类:

public class ElasticSearchSettings
{
    public string ServerUri { get; set; }
    public string DefaultIndex { get; set; } = "defaultindex";
}

ElasticSearch 客户端:

  • 连接到 ElasticSearch,并设定默认索引
public class ElasticSearchClient : IElasticSearchRepository
{
    private readonly ElasticSearchSettings _esSettings;
    private readonly ElasticClient _client;

    public ElasticSearchClient(IOptions<ElasticSearchSettings> esSettings)
    {
        _esSettings = esSettings.Value;

        var settings = new ConnectionSettings(new Uri(_esSettings.ServerUri)).DefaultIndex(_esSettings.DefaultIndex);
        _client = new ElasticClient(settings);
    }

    public ElasticSearchClient(ElasticSearchSettings esSettings)
    {
        _esSettings = esSettings;
        var settings = new ConnectionSettings(new Uri(_esSettings.ServerUri)).DefaultIndex(_esSettings.DefaultIndex);
        _client = new ElasticClient(settings);
    }
}

连接配置上使用密码凭证

ElasticSearch 可以直接在 Uri 上指定密码,如下:

    var uri = new Uri("http://username:[email protected]:9200")
    var settings = new ConnectionConfiguration(uri);

使用连接池

ConnectionSettings 不仅支持单地址的连接方式,同样提供了不同类型的连接池来让你配置客户端,如使用 SniffingConnectionPool 来连接集群中的 3 个 Elasticsearch 节点,客户端将使用该类型的连接池来维护集群中的可用节点列表,并会以循环的方式发送调用请求。

var uris = new[]{
    new Uri("http://localhost:9200"),
    new Uri("http://localhost:9201"),
    new Uri("http://localhost:9202"),};

var connectionPool = new SniffingConnectionPool(uris);var settings = new ConnectionSettings(connectionPool)
    .DefaultIndex("people");

_client = new ElasticClient(settings);

NEST 教程系列 2-1 连接:Configuration options| 配置选项

索引(Indexing)

  • 这里的“索引”需理解为动词,用 indexing 来理解会更好,表示将一份文档插入到 ES 中。

假设有如下类 User.cs

public class User
{
    public Guid Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

索引(Indexing)/添加 一份文档到 ES 中

//同步
var response = _client.IndexDocument<User>(new User
            {
                Id = new Guid("3a351ea1-bfc3-43df-ae12-9c89e22af144"),
                FirstName = "f1",
                LastName = "l1"
            });

//异步
var response = _client.IndexDocumentAsync<User>(new User
            {
                Id = new Guid("82f323e3-b5ec-486b-ac88-1bc5e47ec643"),
                FirstName = "f2",
                LastName = "l2"
            });
  • 目前提供的方法基本上都含有同步和异步版本(异步方法以 *Async 结尾)
  • IndexDocument 方法会判断添加的文档是否已经存在(根据 _id),若存在,则添加失败。
  • NEST 会自动将 Id 属性作为 ES 中的 _id,更多关于 id 的推断方式见此博文:NEST 教程系列 9-3 转换:Id 推断
    • 默认情况下,会使用 camel 命名方式进行转换,你可以使用 ConnectionSettings 对象的 .DefaultFieldNameInferrer(Func<string, string>) 方法来调整默认转换行为,更多关于属性的推断的见此博文:NEST 教程系列 9-4 转换:Field 属性推断

最终请求地址为:

PUT  /users/_doc/3a351ea1-bfc3-43df-ae12-9c89e22af144

查询

通过类 lambda 表达式进行查询

通过 Search 方法进行查询。

var result = _client.Search<User>(s=>s.From(0)
                .Size(10)
                .Query(q=>q.Match(m=>m.Field(f=>f.LastName).Query("l1"))));

请求 URL 如下:

POST /users/_search?typed_keys=true
  • 以上搜索是基于“users”索引来进行搜寻

如何在 ES 上的所有索引上进行搜索?通过 AllIndices(),如下:

var result = _client.Search<User>(s=>s
    .AllIndices()  //指定在所有索引上进行查询
    .From(0)
    .Size(10)
    .Query(q=>q.Match(m=>m.Field(f=>f.LastName).Query("l1"))));

假设有如下文档:

//users 索引
"hits" : [
      {
        "_index" : "users",
        "_type" : "_doc",
        "_id" : "3a351ea1-bfc3-43df-ae12-9c89e22af144",
        "_score" : 1.0,
        "_source" : {
          "id" : "3a351ea1-bfc3-43df-ae12-9c89e22af144",
          "firstName" : "f1",
          "lastName" : "l1"
        }
      },
      {
        "_index" : "users",
        "_type" : "_doc",
        "_id" : "05245504-053c-431a-984f-23e16d8fbbc9",
        "_score" : 1.0,
        "_source" : {
          "id" : "05245504-053c-431a-984f-23e16d8fbbc9",
          "firstName" : "f2",
          "lastName" : "l2"
        }
      }
    ]
// thirdusers 索引
"hits" : [
  {
    "_index" : "thirdusers",
    "_type" : "_doc",
    "_id" : "619ad5f8-c918-46ef-82a8-82a724ca5443",
    "_score" : 1.0,
    "_source" : {
      "firstName" : "f1",
      "lastName" : "l1"
    }
  }
]

则最终可以获取到 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"的文档信息

var request = new SearchRequest(Nest.Indices.All) //在所有索引上查询
{
    From = 0,
    Size = 10,
    Query = new MatchQuery
    {
        Field = Infer.Field<User>(f => f.LastName),
        Query = "l1"
    }
};
var response = _client.Search<User>(request);

生成的请求 URL 为:

POST  /_all/_search?typed_keys=true

通过 .LowLever 属性来使用 Elasticsearch.Net 来进行查询

使用 Elasticsearch.Net 来进行查询的契机:

  • 当客户端存在 bug,即使用上述 NEST 的 Search 和 SearchRequest 异常的时候,可以考虑用 Elasticsearch.Net 提供的查询方式。
  • 当你希望用一个匿名对象或者 JSON 字符串来进行查询的时候。
var response = _client.LowLevel.Search<SearchResponse<User>>("users", PostData.Serializable(new
{
    from = 0,
    size = 10,
    query = new
    {
        match = new
        {
            lastName = "l1"
        }
    }
}));

聚合查询

除了结构化和非结构化查询之外, ES 同样支持聚合(Aggregations)查询:

var result = _client.Search<User>(s => s
    .Size(0) //设置为 0 ,可以让结果只包含聚合的部分:即 hits 属性中没有结果,聚合结果显示在 ”aggregations“
    .Query(q =>
        q.Match(m =>
            m.Field(f => f.FirstName)
                .Query("f2")))
    .Aggregations(a => //使用 terms 聚合,并指定到桶 last_name 中
        a.Terms("last_name", ta =>
            ta.Field(f => f.LastName)))
    );
  • 一般使用 term 聚合来获取每个存储桶的文档数量,其中每个桶将以 lastName 作为关键字。

更多关于聚合的操作可见此:NEST 教程系列 8 聚合:Writing aggregations | 使用聚合

原文地址:https://www.cnblogs.com/deepthought/p/12231714.html

时间: 2024-11-13 19:02:08

Elastcisearch.Nest 7.x 系列`伪`官方翻译:通过 NEST 来快捷试用 Elasticsearch的相关文章

【SFA官方翻译】使用 Kubernetes、Spring Boot 2.0 和 Docker 的微服务快速指南

[SFA官方翻译]使用 Kubernetes.Spring Boot 2.0 和 Docker 的微服务快速指南 原创: Darren Luo SpringForAll社区 今天 原文链接:https://dzone.com/articles/quick-guide-to-microservices-with-kubernetes-sprin 作者:Piotr Mińkowski 译者:Darren Luo 在本教程中你将学习如何使用 Kubernetes 和 Docker 快速启动并运行 Sp

dojo 官方翻译 dojo/json 版本1.10

官方地址:http://dojotoolkit.org/reference-guide/1.10/dojo/json.html#dojo-json require(["dojo/json", "dojo/dom", "dojo/on", "dojo/domReady!"], function(JSON, dom, on){ on(dom.byId("convert"), "click",

dojo 官方翻译 dojo/_base/lang 版本1.10

官方地址:http://dojotoolkit.org/reference-guide/1.10/dojo/_base/lang.html#dojo-base-lang 应用加载声明: require(["dojo/_base/lang"], function(lang){ // lang now contains the module features }); clone() 克隆任何对象或者元素节点,返回:一个新的对象. require(["dojo/_base/lang

dojo 官方翻译 dojo/domReady 版本1.10

官方地址:http://dojotoolkit.org/reference-guide/1.10/dojo/domReady.html#dojo-domready dom加载完成后,执行. require(["dojo/domReady!"], function(){ // will not be called until DOM is ready }); 通常dojo/domReady没有也不需要设定一个返回值,而且,它是被放在加载模块数组的最后加载. require(["

dojo 官方翻译 dojo/string 版本1.10

官方地址:http://dojotoolkit.org/reference-guide/1.10/dojo/string.html#dojo-string require(["dojo/string"], function(string){ var a = string.pad("pad me", 10); var b = string.rep("dup", 10); var c = string.substitute("${repla

android nfc(官方翻译)

为了充分详细的学习nfc相关的知识,决定阅读官方英文文档,并翻译下来供大家阅读. NFC Basics There are two major uses cases when working with NDEF data and Android: Reading NDEF data from an NFC tag Beaming NDEF messages from one device to another with Android Beam? The Tag Dispatch System

dojo 官方翻译 dojo/_base/array

官方地址:http://dojotoolkit.org/reference-guide/1.10/dojo/_base/array.html#dojo-base-array array模块dojo进行了很好的封装,如果想要调用必须先加载该模块: require(["dojo/_base/array"], function(array){ // array contains the features }); indexOf() 返回值:字符串在数组中第一次出现的位置,如果没有找到默认返回

android Bluetooth(官方翻译)

Bluetooth Using the Bluetooth APIs, an Android application can perform the following: 使用蓝牙APIs,一个Android应用可以进行如下操作: Scan for other Bluetooth devices 扫描其他蓝牙设备 Query the local Bluetooth adapter for paired Bluetooth devices 查找本地已经配对的蓝牙设备 Establish RFCOM

WatchKit-Programming-Guide-Apple-Watch开发指南官方翻译及总结

鉴于CSDN的Markdown很多bug,大家请看这里: WatchKit-Programming-Guide-Apple-Watch开发指南官方翻译及总结 Overview ### Developing for Apple Watch Apple Watch可以让用户以一种很私密,不招摇的样式查看信息(官方文档是这样的哈,但是我想大多数人不会不招摇的查看Apple Watch上的信息??).用户可以在不拿出手机的情况下,通过查看Apple Watch快速的获取重要的信息. Apple Watc