Link Search Menu Expand Document Documentation Menu

高阶 .NET 客户端 (OpenSearch.Client) 入门

OpenSearch.Client 是一个高阶 .NET 客户端。它提供强类型请求和响应以及 Query DSL。通过提供自动解析和序列化/反序列化请求和响应的模型,它使您无需构建原始 JSON 请求和解析原始 JSON 响应。如果需要,OpenSearch.Client 还公开了 OpenSearch.Net 低阶客户端。有关客户端的完整 API 文档,请参阅 OpenSearch.Client API 文档

本入门指南说明了如何连接到 OpenSearch、索引文档以及运行查询。有关客户端源代码,请参阅 opensearch-net 存储库

安装 OpenSearch.Client

要安装 OpenSearch.Client,请下载 OpenSearch.Client NuGet 包,并将其添加到您选择的 IDE 项目中。在 Microsoft Visual Studio 中,请遵循以下步骤:

  • 解决方案资源管理器面板中,右键单击您的解决方案或项目,然后选择管理解决方案的 NuGet 包
  • 搜索 OpenSearch.Client NuGet 包,然后选择安装

或者,您可以将 OpenSearch.Client 添加到您的 .csproj 文件中

<Project>
  ...
  <ItemGroup>
    <PackageReference Include="OpenSearch.Client" Version="1.0.0" />
  </ItemGroup>
</Project>

示例

以下示例说明了连接到 OpenSearch、索引文档以及对数据发送查询。它使用 Student 类来表示一个学生,这相当于索引中的一个文档。

public class Student
{
    public int Id { get; init; }
    public string FirstName { get; init; }
    public string LastName { get; init; }
    public int GradYear { get; init; }
    public double Gpa { get; init; }
}

默认情况下,OpenSearch.Client 使用驼峰式命名法将属性名转换为字段名。

连接到 OpenSearch

创建 OpenSearchClient 对象时使用默认构造函数,连接到默认的 OpenSearch 主机 (https://:9200)。

var client  = new OpenSearchClient();

要通过已知地址的单个节点连接到您的 OpenSearch 集群,请在创建 OpenSearch.Client 实例时指定此地址

var nodeAddress = new Uri("http://myserver:9200");
var client = new OpenSearchClient(nodeAddress);

您也可以通过多个节点连接到 OpenSearch。使用节点池连接到 OpenSearch 集群可提供负载均衡和集群故障转移支持等优势。要使用多个节点连接到您的 OpenSearch 集群,请指定它们的地址并为 OpenSearch.Client 实例创建一个 ConnectionSettings 对象

var nodes = new Uri[]
{
    new Uri("http://myserver1:9200"),
    new Uri("http://myserver2:9200"),
    new Uri("http://myserver3:9200")
};

var pool = new StaticConnectionPool(nodes);
var settings = new ConnectionSettings(pool);
var client = new OpenSearchClient(settings);

使用 ConnectionSettings

ConnectionConfiguration 用于向低阶 OpenSearch.Net 客户端传递配置选项。ConnectionSettings 继承自 ConnectionConfiguration 并提供额外的配置选项。要设置节点地址和请求未指定索引名时的默认索引名,请创建一个 ConnectionSettings 对象

var node = new Uri("http://myserver:9200");
var config = new ConnectionSettings(node).DefaultIndex("students");
var client = new OpenSearchClient(config);

索引单个文档

创建一个 Student 实例

var student = new Student { Id = 100, FirstName = "Paulo", LastName = "Santos", Gpa = 3.93, GradYear = 2021 };

要索引一个文档,您可以使用流畅的 Lambda 语法或对象初始化器语法。

使用流畅的 Lambda 语法将此 Student 索引到 students 索引中

var response = client.Index(student, i => i.Index("students"));

使用对象初始化器语法将此 Student 索引到 students 索引中

var response = client.Index(new IndexRequest<Student>(student, "students"));

索引多个文档

您可以使用 OpenSearch.Client 的 IndexMany 方法同时从集合中索引多个文档

var studentArray = new Student[]
{
    new() {Id = 200, FirstName = "Shirley", LastName = "Rodriguez", Gpa = 3.91, GradYear = 2019},
    new() {Id = 300, FirstName = "Nikki", LastName = "Wolf", Gpa = 3.87, GradYear = 2020}
};

var manyResponse = client.IndexMany(studentArray, "students");

搜索文档

要搜索上面索引的学生,您需要构建一个类似于以下 Query DSL 查询的查询

GET students/_search
{
  "query" : {
    "match": {
      "lastName": "Santos"
    }
  }
}

上面的查询是以下显式查询的缩写版本

GET students/_search
{
  "query" : {
    "match": {
      "lastName": {
        "query": "Santos"
      }
    }
  }
}

在 OpenSearch.Client 中,此查询如下所示

var searchResponse = client.Search<Student>(s => s
                                .Index("students")
                                .Query(q => q
                                    .Match(m => m
                                        .Field(fld => fld.LastName)
                                        .Query("Santos"))));

您可以通过访问响应中的文档来打印结果

if (searchResponse.IsValid)
{
    foreach (var s in searchResponse.Documents)
    {
        Console.WriteLine($"{s.Id} {s.LastName} {s.FirstName} {s.Gpa} {s.GradYear}");
    }
}

响应包含一个文档,对应于正确的学生

100 Santos Paulo 3.93 2021

异步使用 OpenSearch.Client 方法

对于需要异步代码的应用程序,OpenSearch.Client 中的所有方法调用都有异步对应项

// synchronous method
var response = client.Index(student, i => i.Index("students"));

// asynchronous method
var response = await client.IndexAsync(student, i => i.Index("students"));

回退到低阶 OpenSearch.Net 客户端

OpenSearch.Client 暴露出低阶 OpenSearch.Net 客户端,如果缺少任何功能,您可以使用它

var lowLevelClient = client.LowLevel;

var searchResponseLow = lowLevelClient.Search<SearchResponse<Student>>("students",
    PostData.Serializable(
        new
        {
            query = new
            {
                match = new
                {
                    lastName = new
                    {
                        query = "Santos"
                    }
                }
            }
        }));

if (searchResponseLow.IsValid)
{
    foreach (var s in searchResponseLow.Documents)
    {
        Console.WriteLine($"{s.Id} {s.LastName} {s.FirstName} {s.Gpa} {s.GradYear}");
    }
}

示例程序

以下是一个完整的示例程序,说明了上述所有概念。它使用上面定义的 Student 类。

using OpenSearch.Client;
using OpenSearch.Net;

namespace NetClientProgram;

internal class Program
{
    private static IOpenSearchClient osClient = new OpenSearchClient();

    public static void Main(string[] args)
    {       
        Console.WriteLine("Indexing one student......");
        var student = new Student { Id = 100, 
                                    FirstName = "Paulo", 
                                    LastName = "Santos", 
                                    Gpa = 3.93, 
                                    GradYear = 2021 };
        var response =  osClient.Index(student, i => i.Index("students"));
        Console.WriteLine(response.IsValid ? "Response received" : "Error");

        Console.WriteLine("Searching for one student......");
        SearchForOneStudent();

        Console.WriteLine("Searching using low-level client......");
        SearchLowLevel();

        Console.WriteLine("Indexing an array of Student objects......");
        var studentArray = new Student[]
        {
            new() { Id = 200, 
                    FirstName = "Shirley", 
                    LastName = "Rodriguez", 
                    Gpa = 3.91, 
                    GradYear = 2019},
            new() { Id = 300, 
                    FirstName = "Nikki", 
                    LastName = "Wolf", 
                    Gpa = 3.87, 
                    GradYear = 2020}
        };
        var manyResponse = osClient.IndexMany(studentArray, "students");
        Console.WriteLine(manyResponse.IsValid ? "Response received" : "Error");
    }

    private static void SearchForOneStudent()
    {
        var searchResponse = osClient.Search<Student>(s => s
                                .Index("students")
                                .Query(q => q
                                    .Match(m => m
                                        .Field(fld => fld.LastName)
                                        .Query("Santos"))));

        PrintResponse(searchResponse);
    }

    private static void SearchForAllStudentsWithANonEmptyLastName()
    {
        var searchResponse = osClient.Search<Student>(s => s
                                .Index("students")
                                .Query(q => q
                        						.Bool(b => b
                        							.Must(m => m.Exists(fld => fld.LastName))
                        							.MustNot(m => m.Term(t => t.Verbatim().Field(fld => fld.LastName).Value(string.Empty)))
                        						)));

        PrintResponse(searchResponse);
    }

    private static void SearchLowLevel()
    {
        // Search for the student using the low-level client
        var lowLevelClient = osClient.LowLevel;

        var searchResponseLow = lowLevelClient.Search<SearchResponse<Student>>
            ("students",
            PostData.Serializable(
                new
                {
                    query = new
                    {
                        match = new
                        {
                            lastName = new
                            {
                                query = "Santos"
                            }
                        }
                    }
                }));

        PrintResponse(searchResponseLow);
    }

    private static void PrintResponse(ISearchResponse<Student> response)
    {
        if (response.IsValid)
        {
            foreach (var s in response.Documents)
            {
                Console.WriteLine($"{s.Id} {s.LastName} " +
                    $"{s.FirstName} {s.Gpa} {s.GradYear}");
            }
        }
        else
        {
            Console.WriteLine("Student not found.");
        }
    }
}