- .NET Clients: other versions:
- Introduction
- Breaking changes
- API Conventions
- Elasticsearch.Net - Low level client
- NEST - High level client
- Troubleshooting
- Search
- Query DSL
- Full text queries
- Term level queries
- Exists Query Usage
- Fuzzy Date Query Usage
- Fuzzy Numeric Query Usage
- Fuzzy Query Usage
- Ids Query Usage
- Prefix Query Usage
- Date Range Query Usage
- Numeric Range Query Usage
- Term Range Query Usage
- Regexp Query Usage
- Term Query Usage
- Terms List Query Usage
- Terms Lookup Query Usage
- Terms Query Usage
- Type Query Usage
- Wildcard Query Usage
- Compound queries
- Joining queries
- Geo queries
- Geo Bounding Box Query Usage
- Geo Distance Query Usage
- Geo Distance Range Query Usage
- Geo Hash Cell Query Usage
- Geo Polygon Query Usage
- Geo Shape Circle Query Usage
- Geo Shape Envelope Query Usage
- Geo Shape Geometry Collection Query Usage
- Geo Shape Indexed Shape Query Usage
- Geo Shape Line String Query Usage
- Geo Shape Multi Line String Query Usage
- Geo Shape Multi Point Query Usage
- Geo Shape Multi Polygon Query Usage
- Geo Shape Point Query Usage
- Geo Shape Polygon Query Usage
- Specialized queries
- Span queries
- NEST specific queries
- Aggregations
- Metric Aggregations
- Average Aggregation Usage
- Cardinality Aggregation Usage
- Extended Stats Aggregation Usage
- Geo Bounds Aggregation Usage
- Geo Centroid Aggregation Usage
- Max Aggregation Usage
- Min Aggregation Usage
- Percentile Ranks Aggregation Usage
- Percentiles Aggregation Usage
- Scripted Metric Aggregation Usage
- Stats Aggregation Usage
- Sum Aggregation Usage
- Top Hits Aggregation Usage
- Value Count Aggregation Usage
- Bucket Aggregations
- Adjacency Matrix Usage
- Children Aggregation Usage
- Date Histogram Aggregation Usage
- Date Range Aggregation Usage
- Filter Aggregation Usage
- Filters Aggregation Usage
- Geo Distance Aggregation Usage
- Geo Hash Grid Aggregation Usage
- Global Aggregation Usage
- Histogram Aggregation Usage
- Ip Range Aggregation Usage
- Missing Aggregation Usage
- Nested Aggregation Usage
- Range Aggregation Usage
- Reverse Nested Aggregation Usage
- Sampler Aggregation Usage
- Significant Terms Aggregation Usage
- Terms Aggregation Usage
- Pipeline Aggregations
- Average Bucket Aggregation Usage
- Bucket Script Aggregation Usage
- Bucket Selector Aggregation Usage
- Cumulative Sum Aggregation Usage
- Derivative Aggregation Usage
- Extended Stats Bucket Aggregation Usage
- Max Bucket Aggregation Usage
- Min Bucket Aggregation Usage
- Moving Average Ewma Aggregation Usage
- Moving Average Holt Linear Aggregation Usage
- Moving Average Holt Winters Aggregation Usage
- Moving Average Linear Aggregation Usage
- Moving Average Simple Aggregation Usage
- Percentiles Bucket Aggregation Usage
- Serial Differencing Aggregation Usage
- Stats Bucket Aggregation Usage
- Sum Bucket Aggregation Usage
- Matrix Aggregations
- Metric Aggregations
WARNING: Version 5.x has passed its EOL date.
This documentation is no longer being maintained and may be removed. If you are running this version, we strongly advise you to upgrade. 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
Connecton 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<byte[]>("people", "person", "1", person); byte[] responseBytes = indexResponse.Body; var asyncIndexResponse = await lowlevelClient.IndexAsync<string>("people", "person", "1", 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<Stream>("people", "person", "1", person); Stream responseStream = indexResponse.Body;
If returning a |
Whether you use an instance of a class, anonymous type, string
, etc. they all are implicitly converted to an instance of PostData<T>
that
the method accepts. Check out the documentation on Post Data to see the other types that are supported.
The generic type parameter on the method specifies the type of the response body. In the last example, we return the response stream 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<Stream>(people); Stream 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<string>("people", "person", new { from = 0, size = 10, query = new { match = new { field = "firstName", query = "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<byte[]>("people", "person", @" { ""from"": 0, ""size"": 10, ""query"": { ""match"": { ""field"": ""firstName"", ""query"": ""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, that does map all requests and responses to types. You can work with
strong 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<byte[]>("people", "person", new { match_all = new {} }); var success = searchResponse.Success; var successOrKnownError = searchResponse.SuccessOrKnownError; var serverError = searchResponse.ServerError; 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. |
|
Details of any error returned from Elasticsearch |
|
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
var settings = new ConnectionConfiguration(new Uri("http://example.com:9200")) .OnRequestCompleted(apiCallDetails => { if (apiCallDetails.HttpStatusCode == 418) { throw new TimeForACoffeeException(); } }); var lowlevelClient = new ElasticLowLevelClient(settings);