- [User Guide](#user-guide)
- [OpenSearch.Client](#opensearchclient)
- [Getting Started](#getting-started)
- [Connecting](#connecting)
- [Indexing](#indexing)
- [Getting a document](#getting-a-document)
- [Searching for documents](#searching-for-documents)
- [Falling back to OpenSearch.Net](#falling-back-to-opensearchnet)
- [OpenSearch.Net.Auth.AwsSigV4](#opensearchnetauthawssigv4)
- [Getting Started](#getting-started-1)
- [Connecting](#connecting-1)
- [Configuring Region & Credentials](#configuring-region--credentials)
- [Amazon OpenSearch Serverless](#amazon-opensearch-serverless)
- [OpenSearch.Net](#opensearchnet)
- [Getting Started](#getting-started-2)
- [Connecting](#connecting-2)
# User Guide
This user guide specifies how to include and use the .NET client in your application.
## [OpenSearch.Client](src/OpenSearch.Client)
### Getting Started
Include OpenSearch.Client in your .csproj file.
```xml
...
```
### Connecting
You can connect to your OpenSearch cluster via a single node, or by specifying multiple nodes using a node pool. Using a node pool has a few advantages over a single node, such as load balancing and cluster failover support.
**Connecting to a single node**
```csharp
var node = new Uri("http://myserver:9200");
var config = new ConnectionSettings(node);
var client = new OpenSearchClient(config);
```
**Connecting to multiple nodes using a connection pool**
```csharp
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);
```
### Indexing
Indexing a document is as simple as:
```csharp
var tweet = new Tweet
{
Id = 1,
User = "kimchy",
PostDate = new DateTime(2009, 11, 15),
Message = "Trying out OSC, so far so good?"
};
var indexingResponse = client.Index(tweet, idx => idx.Index("mytweetindex")); //or specify index via settings.DefaultIndex("mytweetindex");
```
All the calls have async variants:
```csharp
var indexingResponseTask = client.IndexAsync(tweet, idx => idx.Index("mytweetindex")); // returns a Task
// Or, in an async-context
var indexingResponse = await client.IndexAsync(tweet, idx => idx.Index("mytweetindex")); // awaits a Task
```
### Getting a document
```csharp
var getResponse = client.Get(indexingResponse.Id, idx => idx.Index("mytweetindex")); // returns an IGetResponse mapped 1-to-1 with the OpenSearch JSON response
var tweet = getResponse.Source; // the original document
```
### Searching for documents
OpenSearch.Client exposes a fluent interface and a [powerful query DSL](https://opensearch.org/docs/latest/opensearch/query-dsl/index/)
```csharp
var searchResponse = client.Search(s => s
.Index("mytweetindex") //or specify index via settings.DefaultIndex("mytweetindex");
.From(0)
.Size(10)
.Query(q => q
.Term(t => t.User, "kimchy") || q
.Match(mq => mq.Field(f => f.User).Query("osc"))
)
);
```
As well as an object initializer syntax:
```csharp
var request = new SearchRequest
{
From = 0,
Size = 10,
Query = new TermQuery { Field = "user", Value = "kimchy" } ||
new MatchQuery { Field = "description", Query = "OSC" }
};
var searchResponse = client.Search(request);
```
### Falling back to OpenSearch.Net
OpenSearch.Client also includes and exposes the low-level [OpenSearch.Net](https://github.com/opensearch-project/opensearch-net/tree/main/src/OpenSearch.Net) client that you can fall back to in case anything is missing:
```csharp
IOpenSearchLowLevelClient lowLevelClient = client.LowLevel;
// Generic parameter of Search<> is the type of .Body on response
var response = lowLevelClient.Search>("mytweetindex", PostData.Serializable(new
{
from = 0,
size = 10,
fields = new [] {"id", "name"},
query = new {
term = new {
name = new {
value= "OSC"
}
}
}
}));
```
## [OpenSearch.Net.Auth.AwsSigV4](src/OpenSearch.Net.Auth.AwsSigV4)
An implementation of AWS SigV4 request signing for performing IAM authentication against the managed [Amazon OpenSearch Service](https://aws.amazon.com/opensearch-service/).
It can be used with both the low-level OpenSearch.Net client as well as the higher-level OpenSearch.Client client.
### Getting Started
Include OpenSearch.Net.Auth.AwsSigV4 along with your preferred client in your .csproj file.
```xml
...
```
### Connecting
The only wiring required is to use the `AwsSigV4HttpConnection` implementation of `IConnection`.
**With OpenSearch.Client**
```csharp
var endpoint = new Uri("https://example-aaabbbcccddd111222333.us-east-1.es.amazonaws.com");
var connection = new AwsSigV4HttpConnection();
var config = new ConnectionSettings(endpoint, connection);
var client = new OpenSearchClient(config);
```
**With OpenSearch.Net**
```csharp
var endpoint = new Uri("https://example-aaabbbcccddd111222333.us-east-1.es.amazonaws.com");
var connection = new AwsSigV4HttpConnection();
var config = new ConnectionConfiguration(endpoint, connection);
var client = new OpenSearchLowLevelClient(config);
```
### Configuring Region & Credentials
By default, `AwsSigV4HttpConnection` will use the same default logic as the [AWS SDK for .NET](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/creds-assign.html) to determine the credentials and region to use.
However, you may explicitly specify one or both to override this logic, for example:
**Explicitly setting the region, but the credentials coming from the environment**
```shell
export AWS_ACCESS_KEY_ID="..."
export AWS_SECRET_ACCESS_KEY="..."
export AWS_SESSION_TOKEN="..."
```
```csharp
var endpoint = new Uri("https://example-aaabbbcccddd111222333.ap-southeast-2.es.amazonaws.com");
var connection = new AwsSigV4HttpConnection(RegionEndpoint.APSoutheast2);
var config = new ConnectionSettings(endpoint, connection);
var client = new OpenSearchClient(config);
```
**Explicitly setting credentials, such as to assume a role, but the region coming from the environment**
```shell
export AWS_REGION="ap-southeast-2"
```
```csharp
var endpoint = new Uri("https://example-aaabbbcccddd111222333.ap-southeast-2.es.amazonaws.com");
var credentials = new AssumeRoleAWSCredentials(
FallbackCredentialsFactory.GetCredentials(),
"arn:aws:iam::123456789012:role/my-open-search-ingest-role",
"my-ingest-application");
var connection = new AwsSigV4HttpConnection(credentials);
var config = new ConnectionSettings(endpoint, connection);
var client = new OpenSearchClient(config);
```
**Explicitly setting credentials and region, such as to assume a role**
```csharp
var endpoint = new Uri("https://example-aaabbbcccddd111222333.ap-southeast-2.es.amazonaws.com");
var credentials = new AssumeRoleAWSCredentials(
FallbackCredentialsFactory.GetCredentials(),
"arn:aws:iam::123456789012:role/my-open-search-ingest-role",
"my-ingest-application");
var connection = new AwsSigV4HttpConnection(credentials, RegionEndpoint.APSoutheast2);
var config = new ConnectionSettings(endpoint, connection);
var client = new OpenSearchClient(config);
```
### Amazon OpenSearch Serverless
Use the `"aoss"` service code to make requests to [Amazon OpenSearch Serverless](https://aws.amazon.com/opensearch-service/features/serverless/), otherwise all configuration options are identical to above.
```shell
export AWS_ACCESS_KEY_ID="..."
export AWS_SECRET_ACCESS_KEY="..."
export AWS_SESSION_TOKEN="..."
```
```csharp
var endpoint = new Uri("https://aaabbbcccddd111222333.ap-southeast-2.aoss.amazonaws.com");
var connection = new AwsSigV4HttpConnection(RegionEndpoint.APSoutheast2, service: AwsSigV4HttpConnection.OpenSearchServerlessService);
var config = new ConnectionSettings(endpoint, connection);
var client = new OpenSearchClient(config);
```
## [OpenSearch.Net](src/OpenSearch.Net)
A low-level, dependency free client that is a simple .NET wrapper for the REST API. It allows you to build and represent your own requests and responses according to you needs.
### Getting Started
Include OpenSearch.Net in your .csproj file.
```xml
...
```
### Connecting
Connecting using the low-level client is very similar to how you would connect using OpenSearch.Client. In fact, the connection constructs that OpenSearch.Client use are actually OpenSearch.Net constructs. Thus, single node connections and connection pooling still apply when using OpenSearch.Net.
```csharp
var node = new Uri("http://myserver:9200");
var config = new ConnectionConfiguration(node);
var client = new OpenSearchLowLevelClient(config);
```
Note the main difference here is that we are instantiating an `OpenSearchLowLevelClient` rather than `OpenSearchClient`, and `ConnectionConfiguration` instead of `ConnectionSettings`.