Low-level .NET client (OpenSearch.Net)

    The following example illustrates connecting to OpenSearch, indexing documents, and sending queries on the data. It uses the Student class to represent one student, which is equivalent to one document in the index.

    Installing the Opensearch.Net client

    To install Opensearch.Net, download the Opensearch.Net NuGet package and add it to your project in an IDE of your choice. In Microsoft Visual Studio, follow the steps below:

    • In the Solution Explorer panel, right-click on your solution or project and select Manage NuGet Packages for Solution.
    • Search for the OpenSearch.Net NuGet package, and select Install.

    Alternatively, you can add OpenSearch.Net to your .csproj file:

    1. ...
    2. <ItemGroup>
    3. <PackageReference Include="Opensearch.Net" Version="1.0.0" />
    4. </ItemGroup>
    5. </Project>

    Connecting to OpenSearch

    Use the default constructor when creating an OpenSearchLowLevelClient object to connect to the default OpenSearch host (http://localhost:9200).

    1. var client = new OpenSearchLowLevelClient();

    To connect to your OpenSearch cluster through a single node with a known address, create a ConnectionConfiguration object with that address and pass it to the OpenSearch.Net constructor:

    1. var nodeAddress = new Uri("http://myserver:9200");
    2. var config = new ConnectionConfiguration(nodeAddress);
    3. var client = new OpenSearchLowLevelClient(config);

    You can also use a connection pool to manage the nodes in the cluster. Additionally, you can set up a connection configuration to have OpenSearch return the response as formatted JSON.

    1. var uri = new Uri("http://localhost:9200");
    2. var connectionPool = new SingleNodeConnectionPool(uri);
    3. var settings = new ConnectionConfiguration(connectionPool).PrettyJson();
    4. var client = new OpenSearchLowLevelClient(settings);
    1. var uris = new[]
    2. {
    3. new Uri("http://localhost:9200"),
    4. new Uri("http://localhost:9201"),
    5. new Uri("http://localhost:9202")
    6. };
    7. var connectionPool = new SniffingConnectionPool(uris);
    8. var settings = new ConnectionConfiguration(connectionPool).PrettyJson();
    9. var client = new OpenSearchLowLevelClient(settings);

    ConnectionConfiguration is used to pass configuration options to the OpenSearch.Net client. ConnectionSettings inherits from ConnectionConfiguration and provides additional configuration options. The following example uses ConnectionSettings to:

    • Set the default index name for requests that don’t specify the index name.
    • Enable gzip-compressed requests and responses.
    • Signal to OpenSearch to return formatted JSON.
    • Make field names lowercase.

    Indexing one document

    To index a document, you first need to create an instance of the Student class:

    1. var student = new Student {
    2. Id = 100,
    3. FirstName = "Paulo",
    4. LastName = "Santos",
    5. Gpa = 3.93,
    6. GradYear = 2021
    7. };

    Alternatively, you can create an instance of Student using an anonymous type:

    1. var student = new {
    2. Id = 100,
    3. FirstName = "Paulo",
    4. Gpa = 3.93,
    5. GradYear = 2021
    6. };

    Next, upload this Student into the students index using the Index method:

    1. var response = client.Index<StringResponse>("students", "100",
    2. PostData.Serializable(student));
    3. Console.WriteLine(response.Body);

    The generic type parameter of the Index method specifies the response body type. In the example above, the response is a string.

    Indexing many documents using the Bulk API

    To index many documents, use the Bulk API to bundle many operations into one request:

    1. {
    2. new {index = new { _index = "students", _type = "_doc", _id = "200"}},
    3. new { Id = 200,
    4. FirstName = "Shirley",
    5. LastName = "Rodriguez",
    6. Gpa = 3.91,
    7. GradYear = 2019
    8. },
    9. new {index = new { _index = "students", _type = "_doc", _id = "300"}},
    10. new { Id = 300,
    11. FirstName = "Nikki",
    12. LastName = "Wolf",
    13. Gpa = 3.87,
    14. GradYear = 2020
    15. }
    16. };
    17. var manyResponse = client.Bulk<StringResponse>(PostData.MultiJson(studentArray));

    To construct a Query DSL query, use anonymous types within the request body. The following query searches for all students who graduated in 2021:

    1. var searchResponseLow = client.Search<StringResponse>("students",
    2. PostData.Serializable(
    3. new
    4. {
    5. from = 0,
    6. size = 20,
    7. query = new
    8. {
    9. term = new
    10. {
    11. gradYear = new
    12. {
    13. value = 2019
    14. }
    15. }
    16. }
    17. }));
    18. Console.WriteLine(searchResponseLow.Body);

    Alternatively, you can use strings to construct the request. When using strings, you have to escape the " character:

    Using OpenSearch.Net methods asynchronously

    For applications that require asynchronous code, all method calls in OpenSearch.Client have asynchronous counterparts:

    1. // synchronous method
    2. var response = client.Index<StringResponse>("students", "100",
    3. PostData.Serializable(student));
    4. var response = client.IndexAsync<StringResponse>("students", "100",
    5. PostData.Serializable(student));

    Handling exceptions

    By default, OpenSearch.Net does not throw exceptions when an operation is unsuccessful. In particular, OpenSearch.Net does not throw exceptions if the response status code has one of the expected values for this request. For example, the following query searches for a document in an index that does not exist:

    1. @" {
    2. ""query"":
    3. {
    4. ""match"":
    5. {
    6. ""lastName"":
    7. {
    8. ""query"": ""Santos""
    9. }
    10. }
    11. }
    12. }");
    13. Console.WriteLine(searchResponse.Body);

    The response contains an error status code 404, which is one of the expected error codes for search requests, so no exception is thrown. You can see the status code in the status field:

    1. {
    2. "error" : {
    3. "root_cause" : [
    4. {
    5. "type" : "index_not_found_exception",
    6. "reason" : "no such index [students1]",
    7. "index" : "students1",
    8. "resource.id" : "students1",
    9. "resource.type" : "index_or_alias",
    10. "index_uuid" : "_na_"
    11. }
    12. ],
    13. "type" : "index_not_found_exception",
    14. "reason" : "no such index [students1]",
    15. "index" : "students1",
    16. "resource.id" : "students1",
    17. "resource.type" : "index_or_alias",
    18. "index_uuid" : "_na_"
    19. },
    20. "status" : 404
    21. }

    To configure OpenSearch.Net to throw exceptions, turn on the ThrowExceptions() setting on ConnectionConfiguration:

    1. var uri = new Uri("http://localhost:9200");
    2. var connectionPool = new SingleNodeConnectionPool(uri);
    3. var settings = new ConnectionConfiguration(connectionPool)
    4. .PrettyJson().ThrowExceptions();
    5. var client = new OpenSearchLowLevelClient(settings);
    1. Console.WriteLine("Success: " + searchResponse.Success);
    2. Console.WriteLine("SuccessOrKnownError: " + searchResponse.SuccessOrKnownError);
    3. Console.WriteLine("Original Exception: " + searchResponse.OriginalException);
    • Success returns true if the response code is in the 2xx range or the response code has one of the expected values for this request.
    • returns true if the response is successful or the response code is in the 400–501 or 505–599 ranges. If SuccessOrKnownError is true, the request is not retried.
    • OriginalException holds the original exception for the unsuccessful responses.

    The following program creates an index, indexes data, and searches for documents.