NOTE: You are looking at documentation for an older release. For the latest information, see the current release documentation.
Getting started
editGetting started
editElasticsearch.Net is a low level Elasticsearch .NET client that has no dependencies on other libraries and is unopinionated about how you build your requests and responses.
Connecting
editTo connect to Elasticsearch running locally at http://localhost:9200
is as simple as
instantiating a new instance of the client
var lowlevelClient = new ElasticLowLevelClient();
Often you may need to pass additional configuration options to the client such as the address of Elasticsearch if it’s running on
a remote machine. This is where ConnectionConfiguration
comes in; an instance can be instantiated to provide
the client with different configuration values.
var settings = new ConnectionConfiguration(new Uri("http://example.com:9200")) .RequestTimeout(TimeSpan.FromMinutes(2)); var lowlevelClient = new ElasticLowLevelClient(settings);
In this example, a default request timeout was also specified that will be applied to all requests, to determine after how long the client should cancel a request.
There are many other configuration options on ConnectionConfiguration
to control things such as
- Basic Authentication header to send with all requests
- whether the client should connect through a proxy
- whether HTTP compression support should be enabled on the client
Connection pools
editConnectionConfiguration
is not restricted to being passed a single address for Elasticsearch. There are several different
types of Connection pool available, each with different characteristics that can be used to
configure the client. The following example uses a SniffingConnectionPool seeded with the addresses
of three Elasticsearch nodes in the cluster, and the client will use this type of pool to maintain a list of available nodes within the
cluster to which it can send requests in a round-robin fashion.
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 ConnectionConfiguration(connectionPool); var lowlevelClient = new ElasticLowLevelClient(settings);
Indexing
editOnce a client had been configured to connect to Elasticsearch, we need to get some data into the cluster to work with. Imagine we have the following Plain Old CLR Object (POCO)
public class Person { public string FirstName { get; set; } public string LastName { get; set; } }
Indexing a single instance of this POCO, either synchronously or asynchronously, is as simple as
var person = new Person { FirstName = "Martijn", LastName = "Laarman" }; var indexResponse = lowlevelClient.Index<BytesResponse>("people", "person", "1", PostData.Serializable(person)); byte[] responseBytes = indexResponse.Body; var asyncIndexResponse = await lowlevelClient.IndexAsync<StringResponse>("people", "person", "1", PostData.Serializable(person)); string responseString = asyncIndexResponse.Body;
synchronous method that returns an |
|
asynchronous method that returns a |
All available methods within Elasticsearch.Net are exposed as both synchronous and asynchronous versions, with the latter using the idiomatic *Async suffix for the method name.
Both index requests will index the document to the endpoint /people/person/1
.
An anonymous type can also be used to represent the document to index
var person = new { FirstName = "Martijn", LastName = "Laarman" }; var indexResponse = await lowlevelClient.IndexAsync<BytesResponse>("people", "person", "1", PostData.Serializable(person)); byte[] responseStream = indexResponse.Body;
For API’s that take a body you can send the body as an (anonymous) object, byte[], string, stream. Additionally for API’s that
take multilined json you can also send a list of objects or a list of bytes to help you format this. These are all encapsulated
by PostData
and you can use the static methods on that class to send the body in whatever form you have it.
Check out the documentation on Post Data to see all of these permutations in action.
The generic type parameter on the method specifies the type of the response body. In the last example, we return the response as a string from Elasticsearch, forgoing any deserialization.
Bulk indexing
editIf you need to index many documents, Elasticsearch has a Bulk API that can be used to perform many operations in one request
var people = new object[] { new { index = new { _index = "people", _type = "person", _id = "1" }}, new { FirstName = "Martijn", LastName = "Laarman" }, new { index = new { _index = "people", _type = "person", _id = "2" }}, new { FirstName = "Greg", LastName = "Marzouka" }, new { index = new { _index = "people", _type = "person", _id = "3" }}, new { FirstName = "Russ", LastName = "Cam" }, }; var indexResponse = lowlevelClient.Bulk<StringResponse>(PostData.MultiJson(people)); string responseStream = indexResponse.Body;
The client will serialize each item seperately and join items up using the \n
character as required by the Bulk API. Refer to the
Elasticsearch Bulk API documentation for further details and supported operations.
Searching
editNow that we have indexed some documents we can begin to search for them.
The Elasticsearch Query DSL can be expressed using an anonymous type within the request
var searchResponse = lowlevelClient.Search<StringResponse>("people", "person", PostData.Serializable(new { from = 0, size = 10, query = new { match = new { firstName = "Martijn" } } })); var successful = searchResponse.Success; var responseJson = searchResponse.Body;
responseJson
now holds a JSON string for the response. The search endpoint for this query is
/people/person/_search
and it’s possible to search over multiple indices and types by changing the arguments
supplied in the request for index
and type
, respectively.
Strings can also be used to express the request
var searchResponse = lowlevelClient.Search<BytesResponse>("people", "person", @" { ""from"": 0, ""size"": 10, ""query"": { ""match"": { ""firstName"": ""Martijn"" } } }"); var responseBytes = searchResponse.Body;
As you can see, using strings is a little more cumbersome than using anonymous types because of the need to escape
double quotes, but it can be useful at times nonetheless. responseBytes
will contain
the bytes of the response from Elasticsearch.
Elasticsearch.Net does not provide typed objects to represent responses; if you need this, you should consider
using NEST, which does map all requests and responses to types. You can work with
request and response types with Elasticsearch.Net, but it will be up to you as the developer to configure Elasticsearch.Net so that
it understands how to deserialize your types, most likely by providing your own IElasticsearchSerializer
implementation to ConnectionConfiguration
.
Handling Errors
editBy default, Elasticsearch.Net is configured not to throw exceptions if a HTTP response status code is returned that is not in the 200-300 range, nor an expected response status code allowed for a given request e.g. checking if an index exists can return a 404.
The response from low level client calls provides a number of properties that can be used to determine if a call is successful
var searchResponse = lowlevelClient.Search<BytesResponse>("people", "person", PostData.Serializable(new { match_all = new {} })); var success = searchResponse.Success; var successOrKnownError = searchResponse.SuccessOrKnownError; var exception = searchResponse.OriginalException;
Response is in the 200 range, or an expected response for the given request |
|
Response is successful, or has a response code between 400-599 that indicates the request cannot be retried. |
|
If the response is unsuccessful, will hold the original exception. |
Using these details, it is possible to make decisions around what should be done in your application.
The default behaviour of not throwing exceptions can be changed by setting .ThrowExceptions()
on ConnectionConfiguration
var settings = new ConnectionConfiguration(new Uri("http://example.com:9200")) .ThrowExceptions(); var lowlevelClient = new ElasticLowLevelClient(settings);
And if more fine grained control is required, custom exceptions can be thrown using .OnRequestCompleted()
on
ConnectionConfiguration