高阶 .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.");
}
}
}