### Install Elasticsearch .NET Client via Package Manager Console Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/installation.md For Visual Studio users, install the client using the Package Manager Console. Search for 'Elastic.Clients.Elasticsearch' in the NuGet Package Manager UI as an alternative. ```powershell Install-Package Elastic.Clients.Elasticsearch ``` -------------------------------- ### Function Score Query Example Source: https://github.com/elastic/elasticsearch-net/blob/main/tests/Tests/_VerifySnapshots/FunctionScoreQueryUsageTests.VerifyInitializerJson.verified.txt A comprehensive example demonstrating the use of the function_score query with multiple scoring functions, including field_value_factor, random_score, and script_score. It also shows how to apply filters and control boost modes. ```json { query: { function_score: { boost: 1.1, boost_mode: multiply, functions: [ { field_value_factor: { factor: 1.1, field: numberOfCommits, missing: 0.1, modifier: square }, filter: { term: { branches: { value: dev } } }, weight: 3 }, { random_score: { field: _seq_no, seed: 1337 } }, { random_score: { field: _seq_no, seed: random_string } }, { script_score: { script: { source: Math.log(2 + doc['numberOfCommits'].value) } }, weight: 1 }, { weight: 5 } ], max_boost: 20, min_score: 1, query: { match_all: {} }, score_mode: sum, _name: named_query } } } ``` -------------------------------- ### Create an Index Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/getting-started.md Create a new index in Elasticsearch using the client. This example creates an index named 'my_index'. ```csharp var response = await client.Indices.CreateAsync("my_index"); ``` -------------------------------- ### Index a Document Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/getting-started.md Index a document into a specified index. This example defines a 'MyDoc' object and indexes it into 'my_index'. ```csharp var doc = new MyDoc { Id = 1, User = "flobernd", Message = "Trying out the client, so far so good?" }; var response = await client.IndexAsync(doc, x => x.Index("my_index")); ``` -------------------------------- ### Function Score Query Example Source: https://github.com/elastic/elasticsearch-net/blob/main/tests/Tests/_VerifySnapshots/FunctionScoreQueryUsageTests.VerifyDescriptorJson.verified.txt Demonstrates a complex function_score query with multiple functions, filters, and scoring modes. Use this for advanced relevance tuning. ```json { "query": { "function_score": { "boost": 1.1, "boost_mode": "multiply", "functions": [ { "field_value_factor": { "factor": 1.1, "field": "numberOfCommits", "missing": 0.1, "modifier": "square" }, "filter": { "term": { "branches": { "value": "dev" } } }, "weight": 3 }, { "random_score": { "field": "_seq_no", "seed": 1337 } }, { "random_score": { "field": "_seq_no", "seed": "random_string" } }, { "script_score": { "script": { "source": "Math.log(2 + doc['numberOfCommits'].value)" } }, "weight": 1 }, { "weight": 5 } ], "max_boost": 20, "min_score": 1, "query": { "match_all": {} }, "score_mode": "sum", "_name": "named_query" } } } ``` -------------------------------- ### Get a Document by ID Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/getting-started.md Retrieve a document from an index using its ID. The example shows how to access the document's source if the response is valid. ```csharp var response = await client.GetAsync("my-index", id); if (response.IsValidResponse) { var doc = response.Source; } ``` -------------------------------- ### Query ES|QL Results as CSV Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/esql.md Example of querying ES|QL and specifying the response format as CSV. The raw response data is then converted to a UTF-8 string. ```csharp var response = await client.Esql.QueryAsync(r => r .Query("FROM index") .Format("csv") ); var csvContents = Encoding.UTF8.GetString(response.Data); ``` -------------------------------- ### Create Index with Dynamic Templates Source: https://github.com/elastic/elasticsearch-net/blob/main/tests/Tests/_VerifySnapshots/CreateIndexSerializationTests.CreateIndexWithDynamicTemplates_SerializesCorrectly.verified.txt Example of defining dynamic templates within an index creation request. This template applies a 'keyword' type mapping to fields matching 'testPathMatch'. ```json { "mappings": { "dynamic_templates": [ { "testTemplateName": { "mapping": { "type": "keyword" }, "path_match": "testPathMatch" } } ] } } ``` -------------------------------- ### Logging with Exceptions and OnRequestCompleted Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/troubleshoot/logging-with-onrequestcompleted.md This example shows how OnRequestCompleted is invoked even when exceptions are thrown. It configures the client to throw exceptions and logs the request completion. ```csharp var counter = 0; var client = FixedResponseClient.Create( new { }, 500, connectionSettings => connectionSettings .ThrowExceptions() .OnRequestCompleted(r => counter++) ); Assert.Throws(() => client.RootNodeInfo()); <3> counter.Should().Be(1); await Assert.ThrowsAsync(async () => await client.RootNodeInfoAsync()); counter.Should().Be(2); ``` -------------------------------- ### Multi-Search with Descriptor Source: https://github.com/elastic/elasticsearch-net/blob/main/tests/Tests/_VerifySnapshots/MultiSearchApiTests.VerifyDescriptorNdJson.verified.txt Example of a multi-search request using a descriptor object. This is useful for defining multiple search operations within a single request. ```csharp var searchResponse = await client.MultiSearchAsync(ms => ms .Search s .Query(q => q.MatchAll()) .Size(10) ) .Search s .Query(q => q.MatchAll()) .Size(1) ) ); Assert.AreEqual(2, searchResponse.Total); // Two searches were performed Assert.AreEqual(10, searchResponse.ResponsesCollection[0].Total); Assert.AreEqual(1, searchResponse.ResponsesCollection[1].Total); ``` -------------------------------- ### Perform Lookup Join with ESQL Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/linq-to-esql.md Use LookupJoin for cross-index lookups, translating to ES|QL LOOKUP JOIN. This example enriches Product data with Category information. ```csharp public class CategoryLookup { [JsonPropertyName("category_id")] public string CategoryId { get; set; } [JsonPropertyName("category_label")] public string CategoryLabel { get; set; } } var enriched = client.Esql.Query(q => q .LookupJoin( "category-lookup-index", product => product.Id, category => category.CategoryId, (product, category) => new { product.Name, product.Price, category!.CategoryLabel })); ``` -------------------------------- ### Update a Document Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/getting-started.md Update an existing document in an index. This example modifies the 'Message' field of a 'MyDoc' document. ```csharp doc.Message = "This is a new message"; var response = await client.UpdateAsync("my_index", id, u => u .Doc(doc) ); ``` -------------------------------- ### Configure Mappings During Index Creation Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/mappings.md Use this snippet to define custom mappings for an index when it is first created. This ensures the index has the desired schema from the start. ```csharp await client.Indices.CreateAsync(index => index .Index("index") .Mappings(mappings => mappings .Properties(properties => properties .IntegerNumber(x => x.Age!) .Keyword(x => x.FirstName!, keyword => keyword.Index(false)) ) ) ); ``` -------------------------------- ### Implement Custom Serializer Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/source-serialization.md Implement the `Elastic.Transport.Serializer` interface to create a custom source serializer. This example shows a basic implementation that throws `NotImplementedException` for all methods. ```csharp using Elastic.Transport; public class VanillaSerializer : Serializer { public override object? Deserialize(Type type, Stream stream) => throw new NotImplementedException(); public override T Deserialize(Stream stream) => throw new NotImplementedException(); public override ValueTask DeserializeAsync(Type type, Stream stream, CancellationToken cancellationToken = default) => throw new NotImplementedException(); public override ValueTask DeserializeAsync(Stream stream, CancellationToken cancellationToken = default) => throw new NotImplementedException(); public override void Serialize(object? data, Type type, Stream stream, SerializationFormatting formatting = SerializationFormatting.None, CancellationToken cancellationToken = default) => throw new NotImplementedException(); public override void Serialize(T data, Stream stream, SerializationFormatting formatting = SerializationFormatting.None) => throw new NotImplementedException(); public override Task SerializeAsync(object? data, Type type, Stream stream, SerializationFormatting formatting = SerializationFormatting.None, CancellationToken cancellationToken = default) => throw new NotImplementedException(); public override Task SerializeAsync(T data, Stream stream, SerializationFormatting formatting = SerializationFormatting.None, CancellationToken cancellationToken = default) => throw new NotImplementedException(); } ``` -------------------------------- ### Bool Query with Must and Should Clauses Source: https://github.com/elastic/elasticsearch-net/blob/main/tests/Tests/_VerifySnapshots/BoolQueryUsageTests.VerifyDescriptorJson.verified.txt Example of a bool query that requires all documents (match_all) and optionally matches documents where the 'name' field is 'Steve' or 'David'. ```json { query: { bool: { must: { match_all: {} }, should: [ { term: { name: { value: Steve } } }, { term: { name: { value: David } } } ] } } } ``` -------------------------------- ### Search Documents with a Term Query Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/getting-started.md Perform a search operation on an index using a term query. This example searches for documents where the 'User' field matches 'flobernd'. ```csharp var response = await client.SearchAsync(s => s .Indices("my_index") .From(0) .Size(10) .Query(q => q .Term(t => t .Field(x => x.User) .Value("flobernd") ) ) ); if (response.IsValidResponse) { var doc = response.Documents.FirstOrDefault(); } ``` -------------------------------- ### Index a POCO Document Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/source-serialization.md An example of indexing an instance of a POCO document into Elasticsearch. The client's default serializer handles the conversion of the POCO to a JSON source document. ```csharp using Elastic.Clients.Elasticsearch; var document = new MyDocument { StringProperty = "value" }; var indexResponse = await Client.IndexAsync(document); ``` -------------------------------- ### Pagination with Take Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/linq-to-esql.md Demonstrates how to limit the number of results returned using the `Take` method, which translates to ES|QL `LIMIT`. ```csharp // Pagination with `Take` (translates to LIMIT). client.Esql.Query(q => q .Where(p => p.InStock) .OrderByDescending(p => p.Price) .Take(20)); ``` -------------------------------- ### Geo Distance Query Example Source: https://github.com/elastic/elasticsearch-net/blob/main/tests/Tests/_VerifySnapshots/GeoDistanceQueryUsageTests.VerifyDescriptorJson.verified.txt A basic example of a geo_distance query. It searches for documents within 200 meters of the specified location (latitude 34, longitude 34). ```json { "query": { "geo_distance": { "boost": 1.1, "distance": "200m", "distance_type": "arc", "locationPoint": { "lat": 34, "lon": 34 }, "validation_method": "ignore_malformed", "_name": "named_query" } } } ``` -------------------------------- ### Composite Aggregation Sources Initialization (9.1.7 and below) Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/release-notes/breaking-changes.md Illustrates the object initializer syntax for Composite Aggregation sources in versions prior to 9.1.8, using dictionaries. ```csharp var request = new SearchRequest { Aggregations = new Dictionary { { "my_composite", new CompositeAggregation { Sources = [ new Dictionary { { "my_terms", new CompositeAggregationSource { Terms = new CompositeTermsAggregation { // ... } }} }, new Dictionary { { "my_histo", new CompositeAggregationSource { Histogram = new CompositeHistogramAggregation(0.5) { // ... } }} } ] }} } }; ``` -------------------------------- ### Composite Aggregation Sources Initialization (9.1.8 and above) Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/release-notes/breaking-changes.md Demonstrates the updated object initializer syntax for Composite Aggregation sources in version 9.1.8 and above, using KeyValuePair. ```csharp var request = new SearchRequest { Aggregations = new Dictionary { { "my_composite", new CompositeAggregation { Sources = [ new KeyValuePair( "my_terms", new CompositeTermsAggregation <1> { // ... } ), new KeyValuePair( "my_histo", new CompositeHistogramAggregation(0.5) <2> { // ... } ) ] }} } }; ``` -------------------------------- ### Geo Polygon Query Example Source: https://github.com/elastic/elasticsearch-net/blob/main/tests/Tests/_VerifySnapshots/GeoPolygonQueryUsageTests.VerifyDescriptorJson.verified.txt A basic example of a geo_polygon query in Elasticsearch. It specifies a set of points that define the polygon and includes options for boost, ignore_unmapped, validation_method, and a query name. ```json { "query": { "geo_polygon": { "boost": 1.1, "ignore_unmapped": true, "locationPoint": { "points": [ { "lat": 45, "lon": -45 }, { "lat": -34, "lon": -34 }, { "lat": 70, "lon": -70 } ] }, "validation_method": "strict", "_name": "named_query" } } } ``` -------------------------------- ### Run Elasticsearch and Kibana Locally Source: https://github.com/elastic/elasticsearch-net/blob/main/README.md Use this command to quickly set up Elasticsearch and Kibana for local testing. It downloads and runs the latest versions. ```bash curl -fsSL https://elastic.co/start-local | sh ``` -------------------------------- ### Fluent Composite Aggregation Initialization (9.1.8 and above) Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/release-notes/breaking-changes.md Illustrates the updated fluent syntax for Composite Aggregation sources in version 9.1.8 and above, avoiding previous ambiguities. ```csharp var descriptor = new SearchRequestDescriptor() .Aggregations(aggs => aggs .Add("my_composize", agg => agg .Composite(composite => composite .Sources(sources => sources .Add("my_terms", x => x.Terms(/* ... */)) .Add("my_histo", x => x.Histogram(/* ... */)) ) ) ) ); ``` -------------------------------- ### Container Type Handling: Query and Aggregation Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/release-notes/breaking-changes.md Illustrates the change in how container types like Query and Aggregation are handled, moving from static factory methods to regular properties. The new recommended way of inspecting container types using pattern matching is also shown. ```csharp // 8.x new SearchRequest { Query = Query.MatchAll( new MatchAllQuery { } ) }; // 9.0 new SearchRequest { Query = new Query { MatchAll = new MatchAllQuery { } } }; ``` ```csharp var query = new Query(); if (query.Nested is { } nested) { // We have a nested query. } ``` -------------------------------- ### Delete an Index Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/getting-started.md Delete an entire index from Elasticsearch. This example deletes the index named 'my_index'. ```csharp var response = await client.Indices.DeleteAsync("my_index"); ``` -------------------------------- ### Fluent Composite Aggregation Initialization (9.1.7 and below) Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/release-notes/breaking-changes.md Shows the fluent syntax for initializing Composite Aggregation sources in versions prior to 9.1.8, using a params overload. ```csharp var descriptor = new SearchRequestDescriptor() .Aggregations(aggs => aggs .Add("my_composize", agg => agg .Composite(composite => composite .Sources( <1> x => x.Add("my_terms", x => x.Terms(/* ... */)), <2> x => x.Add("my_histo", x => x.Histogram(/* ... */)) <3> ) ) ) ); ``` -------------------------------- ### Initialize Connection with Sniffing Connection Pool Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/troubleshoot/audit-trail.md Sets up a connection pool that sniffs on startup and pings before first usage to gather audit trail events. This is useful for observing initial connection events. ```csharp var pool = new SniffingConnectionPool(new []{ TestConnectionSettings.CreateUri() }); var connectionSettings = new ConnectionSettings(pool) .DefaultMappingFor(i => i .IndexName("project") ); var client = new ElasticClient(connectionSettings); ``` -------------------------------- ### Index Customer Document with Custom Serialization Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/source-serialization.md Demonstrates how to create a `Customer` object and index it into Elasticsearch using the client, which will leverage the custom converter for serialization. ```csharp var customer = new Customer { CustomerName = "Customer Ltd", CustomerType = CustomerType.Enhanced }; var indexResponse = await Client.IndexAsync(customer); ``` -------------------------------- ### Get a Document by ID Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/examples.md Retrieves a Tweet document by its ID from 'my-tweet-index'. The document is deserialized into the Tweet class. ```csharp var response = await client.GetAsync(1, x => x.Index("my-tweet-index")); if (response.IsValidResponse) { var tweet = response.Source; } ``` -------------------------------- ### Quick Compile and Run Integration Tests Source: https://github.com/elastic/elasticsearch-net/blob/main/CONTRIBUTING.md Compiles the solution and runs integration tests against a specified Elasticsearch version. The first run may download Elasticsearch and its plugins. ```bat .\build.bat integrate [Elasticsearch Version Number e.g. 8.3.2] ``` -------------------------------- ### Verify Audit Trail Event Durations Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/troubleshoot/audit-trail.md Checks that each audit event in the trail has a non-negative duration by ensuring the Ended DateTime is not before the Started DateTime. ```csharp response.ApiCall.AuditTrail .Should().OnlyContain(a => a.Ended - a.Started >= TimeSpan.Zero); ``` -------------------------------- ### Set Request Path Parameters in C# (8.x vs 9.0) Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/release-notes/index.md Illustrates the difference in setting request path parameters between 8.x and 9.0. In 8.x, parameters were set via constructor, while 9.0 uses properties. ```csharp // 8.x and 9.0 var request = new SearchRequest(Indices.All); ``` ```csharp // 9.0 var request = new SearchRequest { Indices = Indices.All }; var indices = request.Indices; request.Indices = "my_index"; ``` -------------------------------- ### ES|QL Source Commands: FROM and ROW Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/linq-to-esql.md Demonstrates the use of `FROM` to query indices and `ROW` to produce synthetic data. Supports index patterns with `FROM`. ```csharp using Elastic.Esql.Extensions; client.Esql.Query(q => q .From("products") <1> .Where(p => p.InStock)); client.Esql.Query(q => q .From("products-*") <2> .Take(10)); client.Esql.Query(q => q .Row(() => new { name = "Test", price_usd = 9.99 })); <3> ``` -------------------------------- ### Connect to Elasticsearch with API Key Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/getting-started.md Instantiate the Elasticsearch client using your deployment's endpoint URL and an API key for authentication. Ensure you replace placeholder values with your actual credentials. ```csharp using Elastic.Clients.Elasticsearch; using Elastic.Transport; var settings = new ElasticsearchClientSettings(new Uri("")) .Authentication(new ApiKey("")); var client = new ElasticsearchClient(settings); ``` -------------------------------- ### Run Build Script (Windows) Source: https://github.com/elastic/elasticsearch-net/blob/main/CONTRIBUTING.md Execute the build script on Windows to pull dependencies and run the default build target. ```bat .\build.bat ``` -------------------------------- ### Run Build Script (OSX/Linux) Source: https://github.com/elastic/elasticsearch-net/blob/main/CONTRIBUTING.md Execute the build script on OSX or Linux to pull dependencies and run the default build target. ```sh ./build.sh ``` -------------------------------- ### IpPrefixAggregation Initialization Source: https://github.com/elastic/elasticsearch-net/blob/main/tests/Tests/_VerifySnapshots/IpPrefixAggregationUsageTests.VerifyInitializerJson.verified.txt Demonstrates the initialization of an IpPrefixAggregation with a field and prefix length. This is used to aggregate IP addresses within specified subnets. ```json { aggregations: { ipv4-subnets: { ip_prefix: { field: leadDeveloper.ipAddress, prefix_length: 24 }, meta: { foo: bar } } }, query: { term: { type: { value: project } } }, size: 0 } ``` -------------------------------- ### Initialize Elasticsearch Client Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/examples.md Initializes a new instance of the ElasticsearchClient. Assumes an unsecured Elasticsearch server running on http://localhost:9200. ```csharp using Elastic.Clients.Elasticsearch; var client = new ElasticsearchClient(); ``` -------------------------------- ### Add Elasticsearch .NET Client via .NET CLI Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/installation.md Use this command to add the Elasticsearch client package to your SDK-style project. ```text dotnet add package Elastic.Clients.Elasticsearch ``` -------------------------------- ### Multi-Search with NDJSON Source: https://github.com/elastic/elasticsearch-net/blob/main/tests/Tests/_VerifySnapshots/MultiSearchApiTests.VerifyDescriptorNdJson.verified.txt Example of a multi-search request using the NDJSON (Newline Delimited JSON) format. This format is often used for bulk operations and can be more efficient for certain use cases. ```csharp var searchResponse = await client.MultiSearchAsync("users", "projects", "logs", ms => ms .AllIndices() .Search s .Query(q => q.MatchAll()) .Size(10) ) .Search s .Query(q => q.MatchAll()) .Size(1) ) .Search s .Query(q => q.MatchAll()) .Size(5) ) ); Assert.AreEqual(3, searchResponse.Total); Assert.AreEqual(10, searchResponse.ResponsesCollection[0].Total); Assert.AreEqual(1, searchResponse.ResponsesCollection[1].Total); Assert.AreEqual(5, searchResponse.ResponsesCollection[2].Total); ``` -------------------------------- ### Sorting: Ascending, Descending, and Multi-Column Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/linq-to-esql.md Shows how to sort query results in ascending, descending, and multi-column order using `OrderBy`, `ThenByDescending`. ```csharp // Sort ascending. client.Esql.Query(q => q.OrderBy(p => p.Price)); // Sort descending. client.Esql.Query(q => q.OrderByDescending(p => p.Price)); // Multi-column sort. client.Esql.Query(q => q .OrderBy(p => p.Brand) .ThenByDescending(p => p.Price)); ``` -------------------------------- ### Basic Search Query with Aggregation and Filter Source: https://github.com/elastic/elasticsearch-net/blob/main/tests/Tests/_VerifySnapshots/SearchApiTests.VerifyDescriptorJson.verified.txt Constructs a search request including a terms aggregation on 'startedOn', a post filter for 'state: Stable', and basic pagination (from, size). Use this for complex searches requiring both data retrieval and aggregated insights. ```json { aggregations: { startDates: { terms: { field: startedOn } } }, from: 10, post_filter: { term: { state: { value: Stable } } }, query: { match_all: {} }, size: 20 } ``` -------------------------------- ### Projections: Selecting Specific Fields Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/linq-to-esql.md Illustrates how to use the `Select` method to choose specific fields or create transformed results, including renaming fields. ```csharp // Select specific fields into an anonymous type. var query = client.Esql.CreateQuery() .Select(p => new { p.Name, p.Price }); // Rename fields in the projection. var query = client.Esql.CreateQuery() .Select(p => new { ProductName = p.Name, p.Price, p.InStock }); ``` -------------------------------- ### Update Document by ID Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/examples.md Update an existing document by providing its ID and the updated document object. This example shows how to modify a property on a tweet object before sending it in the update request. ```csharp tweet.Message = "This is a new message"; <1> var response = await client.UpdateAsync("my-tweet-index", 1, u => u .Doc(tweet) ); <2> if (response.IsValidResponse) { Console.WriteLine("Update document succeeded."); } ``` -------------------------------- ### POCO with Elasticsearch Query Type Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/source-serialization.md Example of a POCO that includes an Elasticsearch-specific type, such as a Query object for percolation. It uses a custom JsonConverter to ensure correct serialization of the Elasticsearch type. ```csharp using Elastic.Clients.Elasticsearch.QueryDsl; using Elastic.Clients.Elasticsearch.Serialization; public class MyPercolationDocument { [JsonConverter(typeof(RequestResponseConverter))] public Query Query { get; set; } public string Category { get; set; } } ``` -------------------------------- ### Fluent API for Union Types Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/release-notes/index.md Illustrates the fluent syntax for union and variant types, showing how to construct queries using different possible types within the union. ```csharp // TermsQueryField : Union, TermsLookup> new TermsQueryDescriptor() .Terms(x => x.Value("a", "b", "c")) <1> .Terms(x => x.Lookup(x => x.Index("index").Id("id"))); <2> ``` -------------------------------- ### Geohash Grid Aggregation Query Source: https://github.com/elastic/elasticsearch-net/blob/main/tests/Tests/_VerifySnapshots/GeohashGridAggregationUsageTests.VerifyDescriptorJson.verified.txt Example of a Geohash Grid aggregation query. It specifies the field for geospatial data, precision of the geohash cells, shard size, and the maximum number of buckets to return. ```json { "aggregations": { "my_geohash_grid": { "geohash_grid": { "field": "locationPoint", "precision": 3, "shard_size": 100, "size": 1000 } } }, "query": { "term": { "type": { "value": "project" } } }, "size": 0 } ``` -------------------------------- ### 8.x Container with Additional Properties Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/release-notes/index.md Demonstrates setting additional properties on a container initialized in 8.x, requiring a temporary variable. ```csharp // 8.x var agg = Aggregation.Max(new MaxAggregation { Field = "my_field" }); agg.Aggregations ??= new Dictionary(); agg.Aggregations.Add("my_sub_agg", Aggregation.Terms(new TermsAggregation())); ``` -------------------------------- ### Elasticsearch Aggregation Query with Cumulative Sum Source: https://github.com/elastic/elasticsearch-net/blob/main/tests/Tests/_VerifySnapshots/CumulativeSumAggregationUsageTests.VerifyDescriptorJson.verified.txt Constructs an Elasticsearch query that includes a date histogram aggregation and a nested cumulative sum aggregation. This example calculates the cumulative number of commits per month for projects. ```csharp await this.fluentCluster.VerifyDescriptorAsync(d => d .Size(0) .Query(q => q.Term(t => t.Field("type.keyword").Value("project"))) .Aggregations(a => a .DateHistogram("projects_started_per_month", dh => dh .Field("startedOn") .CalendarInterval(CalendarInterval.Month) .Aggregations(aa => aa .Sum("commits", s => s.Field("numberOfCommits")) .CumulativeSum("cumulative_commits", cs => cs.Path("commits")) ) ) ) ) ``` -------------------------------- ### Elasticsearch CA Certificate Fingerprint Output Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/connecting.md When Elasticsearch starts for the first time with security features enabled, it outputs the HTTP CA certificate SHA-256 fingerprint. This fingerprint is used by the client to trust the cluster's CA certificate for HTTPS connections. ```sh ---------------------------------------------------------------- -> Elasticsearch security features have been automatically configured! -> Authentication is enabled and cluster connections are encrypted. -> Password for the elastic user (reset with `bin/elasticsearch-reset-password -u elastic`): lhQpLELkjkrawaBoaz0Q -> HTTP CA certificate SHA-256 fingerprint: a52dd93511e8c6045e21f16654b77c9ee0f34aea26d9f40320b531c474676228 ... ---------------------------------------------------------------- ``` -------------------------------- ### Fluent API for Dictionary with Key-Only Additions Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/release-notes/index.md Shows how to add entries to a dictionary where the value type does not require initialization, using fluent API with key-only specifications. ```csharp // Dictionary() new CreateIndexRequestDescriptor("index") // ... all previous overloads ... .Aliases(aliases => aliases // Fluent: Nested. .Add("key") // Key only. ) .Aliases("key") // Key only: Single element. .Aliases("first", "second") // Key only: Multiple elements (params). ``` -------------------------------- ### Enable HTTP Pipelining Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/_options_on_elasticsearchclientsettings.md Enables HTTP pipelining. The default is true. ```csharp new ConnectionSettings().EnableHttpPipelining(true) ``` -------------------------------- ### 8.x Container Initialization Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/release-notes/index.md In 8.x, container types required static factory methods for initialization, necessitating temporary variables for setting additional properties. ```csharp // 8.x var agg = Aggregation.Max(new MaxAggregation { Field = "my_field" }); ``` -------------------------------- ### Configure Logging with OnRequestCompleted Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/troubleshoot/logging-with-onrequestcompleted.md This snippet demonstrates how to set up a connection with a custom OnRequestCompleted handler to log request and response details. It includes logic to capture request and response bodies when available. ```csharp var list = new List(); var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); var settings = new ConnectionSettings(connectionPool, new InMemoryConnection()) .DefaultIndex("default-index") .OnRequestCompleted(apiCallDetails => { // log out the request and the request body, if one exists for the type of request if (apiCallDetails.RequestBodyInBytes != null) { list.Add( $"{apiCallDetails.HttpMethod} {apiCallDetails.Uri} " + $"{Encoding.UTF8.GetString(apiCallDetails.RequestBodyInBytes)}"); } else { list.Add($"{apiCallDetails.HttpMethod} {apiCallDetails.Uri}"); } // log out the response and the response body, if one exists for the type of response if (apiCallDetails.ResponseBodyInBytes != null) { list.Add($"Status: {apiCallDetails.HttpStatusCode}" + $"{Encoding.UTF8.GetString(apiCallDetails.ResponseBodyInBytes)}"); } else { list.Add($"Status: {apiCallDetails.HttpStatusCode}"); } }); var client = new ElasticClient(settings); var syncResponse = client.Search(s => s <1> .AllIndices() .Scroll("2m") .Sort(ss => ss .Ascending(SortSpecialField.DocumentIndexOrder) ) ); list.Count.Should().Be(2); var asyncResponse = await client.SearchAsync(s => s <2> .RequestConfiguration(r => r .DisableDirectStreaming() ) .AllIndices() .Scroll("10m") .Sort(ss => ss .Ascending(SortSpecialField.DocumentIndexOrder) ) ); list.Count.Should().Be(4); list.Should().BeEquivalentTo(new[] { @"POST http://localhost:9200/_all/_search?typed_keys=true&scroll=2m", <3> @"Status: 200", @"POST http://localhost:9200/_all/_search?typed_keys=true&scroll=10m {\"sort\":[{\"_doc\":{\"order\":\"asc\"}}]}", <4> @"Status: 200" }); ``` -------------------------------- ### Enable HTTP Compression Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/_options_on_elasticsearchclientsettings.md Enables gzip compression for both requests and responses. ```csharp new ConnectionSettings().EnableHttpCompression() ``` -------------------------------- ### Fluent API for IDictionary Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/release-notes/index.md Illustrates the fluent API support for IDictionary types, covering scalar and fluent nested additions, as well as key-only additions for specific dictionary configurations. ```csharp new SearchRequestDescriptor() .Aggregations(new Dictionary()) // Scalar. .Aggregations(aggs => aggs // Fluent: Nested. .Add("key", new MaxAggregation()) .Add("key", x => x.Max()) ) .AddAggregation("key", new MaxAggregation()) // Scalar. .AddAggregation("key", x => x.Max()); // Fluent. ``` -------------------------------- ### Aggregations: Count per Group Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/linq-to-esql.md Illustrates how to perform a count aggregation per group using `GroupBy` and `Select`. ```csharp // Count per group. var brandCounts = client.Esql.Query(q => q .GroupBy(p => p.Brand) .Select(g => new { Brand = g.Key, Count = g.Count() })); ``` -------------------------------- ### Search with Object Initializer API Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/query.md Utilize the Object Initializer API for a more declarative approach to building search requests. ```csharp var response = await client.SearchAsync( new SearchRequest("persons") { Query = new Query { Term = new TermQuery { Field = Infer.Field(x => x.FirstName), Value = "Florian" } }, Size = 10 } ); ``` -------------------------------- ### Filtering with Range and String Methods Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/linq-to-esql.md Shows how to apply range filters and use string methods like `Contains` and `StartsWith` for filtering. ```csharp // Range. client.Esql.Query(q => q .Where(p => p.Price >= 100 && p.Price <= 300)); // Contains → LIKE "*value*" client.Esql.Query(q => q.Where(p => p.Name.Contains("Pro"))); // StartsWith → LIKE "value*" client.Esql.Query(q => q.Where(p => p.Name.StartsWith("Ultra"))); ``` -------------------------------- ### Fluent API for ICollection> Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/release-notes/index.md Explains the fluent API for ICollection> types, which mirrors the IDictionary fluent API for managing ordered dictionaries. ```csharp new PutMappingRequestDescriptor("index") .DynamicTemplates(new List>()) // Scalar. .DynamicTemplates(x => x // Fluent: Nested. .Add("key", new DynamicTemplate()) // Scalar: Key + Value. .Add("key", x => x.Mapping(new TextProperty())) // Fluent: Key + Value. ) .AddDynamicTemplate("key", new DynamicTemplate()) // Scalar: Key + Value. .AddDynamicTemplate("key", x => x.Runtime(x => x.Format("123"))); // Fluent: Key + Value. ``` -------------------------------- ### Compile Solution (Skip Tests) Source: https://github.com/elastic/elasticsearch-net/blob/main/CONTRIBUTING.md Compiles the solution without running any tests. ```bat .\build.bat skiptests ``` -------------------------------- ### Manually Add Elasticsearch .NET Client Reference Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/installation.md Alternatively, you can manually add the package reference to your project file. Ensure you replace '{latest-version}' with the actual latest version from NuGet.org. ```xml ``` -------------------------------- ### Fluent API for ICollection Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/release-notes/index.md Demonstrates the usage of the fluent API for ICollection properties, including single and multiple element additions using both scalar and fluent query constructs. ```csharp new SearchRequestDescriptor() .Query(q => q .Bool(b => b .Must(new Query()) // Scalar: Single element. .Must(new Query(), new Query()) // Scalar: Multiple elements (params). .Must(m => m.MatchAll()) // Fluent: Single element. .Must(m => m.MatchAll(), m => m.MatchNone()) // Fluent: Multiple elements (params). ) ); ``` -------------------------------- ### Sorting for Aggregations (9.0) Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/release-notes/index.md Illustrates the improved syntax for specifying sort orders for aggregations in version 9.0, including fluent add syntax. ```csharp new SearchRequestDescriptor() .Aggregations(aggs => aggs .Add("my_terms", agg => agg .Terms(terms => terms // 8.x syntax. .Order(new List> { new KeyValuePair("_key", SortOrder.Desc) }) // 9.0 fluent syntax. .Order(x => x .Add(x => x.Age, SortOrder.Asc) .Add("_key", SortOrder.Desc) ) // 9.0 fluent add syntax (valid for all dictionary-like values). .AddOrder("_key", SortOrder.Desc) ) ) ); ``` -------------------------------- ### Configure ElasticsearchClientSettings Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/_options_on_elasticsearchclientsettings.md Use ElasticsearchClientSettings to configure options like default mappings, enable debug mode, pretty JSON, and set request timeouts. Instantiate ElasticsearchClient with these settings. ```csharp var settings= new ElasticsearchClientSettings() .DefaultMappingFor(i => i .IndexName("my-projects") .IdProperty(p => p.Name) ) .EnableDebugMode() .PrettyJson() .RequestTimeout(TimeSpan.FromMinutes(2)); var client = new ElasticsearchClient(settings); ``` -------------------------------- ### Compose ES|QL Queries with LINQ Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/release-notes/index.md Use familiar LINQ operators to compose ES|QL queries. The provider automatically handles translation, parameterization, and deserialization. ```csharp var products = client.Esql.Query(q => q .From("products") .Where(p => p.InStock) .OrderByDescending(p => p.Price) .Take(10)); foreach (var product in products) Console.WriteLine($"{product.Name}: {product.Price}"); ``` -------------------------------- ### Filtering with Null Checks and Enum Comparisons Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/linq-to-esql.md Demonstrates how to perform null checks and compare enum values within query filters. ```csharp // Null checks (translates to IS NOT NULL / IS NULL). client.Esql.Query(q => q.Where(o => o.Notes != null)); // Enum comparison. client.Esql.Query(q => q.Where(o => o.Status == OrderStatus.Delivered)); ``` -------------------------------- ### Configure ESQL Query Options Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/linq-to-esql.md Utilize EsqlQueryOptions to set per-query configurations such as Query DSL filters, timezones, and transport options. This allows fine-grained control over query execution. ```csharp using Elastic.Clients.Elasticsearch.Esql; var options = new EsqlQueryOptions { // Apply a Query DSL filter before the ES|QL query runs. Filter = new TermQuery { Field = "environment", Value = "production" }, // Timezone for date operations (supported for Elasticsearch 9.4 and above). TimeZone = "Europe/Berlin", // Allow partial results if some shards are unavailable. AllowPartialResults = true, // Remove entirely null columns from the response. DropNullColumns = true }; var results = client.Esql.Query(q => q .Where(p => p.InStock), queryOptions: options); ``` -------------------------------- ### Aggregations: Multiple Aggregations per Group Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/linq-to-esql.md Shows how to calculate multiple aggregate values (count, average, min, max) for each group. ```csharp // Multiple aggregations. var stats = client.Esql.Query(q => q .Where(p => p.InStock) .GroupBy(p => p.Brand) .Select(g => new { Brand = g.Key, Count = g.Count(), AvgPrice = g.Average(p => p.Price), MinPrice = g.Min(p => p.Price), MaxPrice = g.Max(p => p.Price) })); ``` -------------------------------- ### Advanced LINQ to ES|QL Composition Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/linq-to-esql.md Uses `CreateQuery` for advanced composition of LINQ queries, allowing inspection of the generated ES|QL before execution. Results can be retrieved as an async enumerable. ```csharp var query = client.Esql.CreateQuery() .From("products") .Where(p => p.Category == ProductCategory.Electronics) .OrderBy(p => p.Price); // Inspect the generated ES|QL Console.WriteLine(query.ToEsqlString()); // Execute await foreach (var product in query.AsAsyncEnumerable()) Console.WriteLine(product.Name); ``` -------------------------------- ### Globally Enable TCP Statistics Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/troubleshoot/debug-information.md Configure `ConnectionSettings` to enable the collection of TCP statistics for all outgoing requests. This helps in diagnosing network-related issues. ```csharp var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); var settings = new ConnectionSettings(connectionPool) .EnableTcpStats(); var client = new ElasticClient(settings); ``` -------------------------------- ### Basic Authentication Header Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/_options_on_elasticsearchclientsettings.md Use BasicAuthentication for basic HTTP header authentication. ```csharp new BasicAuthentication("username", "password") ``` -------------------------------- ### 9.0 Container Variant Inspection with Pattern Matching Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/release-notes/index.md The recommended way to inspect container types in 9.0 is using simple pattern matching. ```csharp var query = new Query(); if (query.Nested is { } nested) { // We have a nested query. } ``` -------------------------------- ### Connect to Cloud Deployment with API Key Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/connecting.md Use this snippet to connect to an Elasticsearch deployment in the cloud using an API key. Replace placeholders with your cluster's endpoint URL and API key. ```csharp using Elastic.Clients.Elasticsearch; using Elastic.Transport; var settings = new ElasticsearchClientSettings(new Uri("")) .Authentication(new ApiKey("")); <1> var client = new ElasticsearchClient(settings); ``` -------------------------------- ### Define Product Document Type Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/linq-to-esql.md Defines the Product class with property mappings for ES|QL using System.Text.Json attributes. This model is used for LINQ to ES|QL queries. ```csharp using System.Text.Json.Serialization; public class Product { [JsonPropertyName("product_id")] public string Id { get; set; } public string Name { get; set; } public string Brand { get; set; } [JsonPropertyName("price_usd")] public double Price { get; set; } [JsonPropertyName("in_stock")] public bool InStock { get; set; } [JsonPropertyName("stock_quantity")] public int StockQuantity { get; set; } public ProductCategory Category { get; set; } public List Tags { get; set; } } [JsonConverter(typeof(JsonStringEnumConverter))] public enum ProductCategory { Electronics, Clothing, Books, Home, Sports } ``` -------------------------------- ### Convenient Sorting in Search Requests (9.0) Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/release-notes/index.md Demonstrates the more convenient fluent API for applying sort orders to search requests in version 9.0. ```csharp var search = new SearchRequestDescriptor() .Sort( x => x.Score(), x => x.Score(x => x.Order(SortOrder.Desc)), x => x.Field(x => x.FirstName), x => x.Field(x => x.Age, x => x.Order(SortOrder.Desc)), x => x.Field(x => x.Age, SortOrder.Desc) // 7.x syntax x => x.Field(x => x.Field(x => x.FirstName).Order(SortOrder.Desc)) ); ``` -------------------------------- ### Alternative IndexRequestDescriptor Usage Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/release-notes/breaking-changes.md Demonstrates the alternative way to construct an IndexRequestDescriptor and call the IndexAsync method using the new API semantics, specifying the index name and ID explicitly. ```csharp // Descriptor constructor. new IndexRequestDescriptor(document, "my_index", Id.From(document)); // Request API method. await client.IndexAsync(document, "my_index", Id.From(document), ...); ``` -------------------------------- ### Submit Server-Side Async Queries Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/linq-to-esql.md Submit long-running ES|QL queries as server-side async queries. This allows the server to process the query in the background while the client polls for results. ```csharp await using var asyncQuery = await client.Esql.SubmitAsyncQueryAsync( q => q.Where(p => p.InStock), asyncQueryOptions: new EsqlAsyncQueryOptions { WaitForCompletionTimeout = TimeSpan.FromSeconds(5), KeepAlive = TimeSpan.FromMinutes(10), KeepOnCompletion = true }); await asyncQuery.WaitForCompletionAsync(); await foreach (var product in asyncQuery.AsAsyncEnumerable()) Console.WriteLine(product.Name); foreach (var product in asyncQuery.AsEnumerable()) Console.WriteLine(product.Name); ``` -------------------------------- ### Enable ThreadPool Statistics for All Requests Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/troubleshoot/debug-information.md Configure ConnectionSettings to collect ThreadPool statistics for all requests made by the client. This is useful for global debugging. ```csharp var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); var settings = new ConnectionSettings(connectionPool) .EnableThreadPoolStats(); var client = new ElasticClient(settings); ``` -------------------------------- ### Fluent API for Dictionary with Collection Values Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/release-notes/index.md Demonstrates fluent API usage for dictionaries where the value type is a collection, including `params` overloads for adding multiple items. ```csharp // Dictionary> new CompletionSuggesterDescriptor() // ... all previous overloads ... .AddContext("key", new CompletionContext{ Context = new Context("first") }, new CompletionContext{ Context = new Context("second") } ) .AddContext("key", x => x.Context(x => x.Category("first")), x => x.Context(x => x.Category("second")) ); ``` -------------------------------- ### 9.0 Improved Container Initialization Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/release-notes/index.md In 9.0, container variants are regular properties, allowing direct initialization and property setting in one go using object initializers. ```csharp // 9.0 var agg = new Aggregation { Max = new MaxAggregation { Field = "my_field" }, Aggregations = new Dictionary { { "my_sub_agg", new Aggregation{ Terms = new TermsAggregation() } } } }; ``` -------------------------------- ### Filtering with Equality and Numeric Comparisons Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/linq-to-esql.md Shows how to filter query results using simple equality checks and numeric comparisons in C#. ```csharp // Simple equality. client.Esql.Query(q => q.Where(p => p.Brand == "TechCorp")); // Numeric comparison. client.Esql.Query(q => q.Where(p => p.Price > 500)); ``` -------------------------------- ### Serialize Combined AND Queries as Must Clauses Source: https://github.com/elastic/elasticsearch-net/blob/main/tests/Tests/_VerifySnapshots/QueryOperatorSerializationTests.SearchQueriesCombinedWithAndOperator_SerializeAsMustClauses.verified.txt Demonstrates serializing a boolean query with multiple 'term' clauses combined by an AND operator into 'must' clauses. ```json { query: { bool: { must: [ { term: { name: { value: x } } }, { term: { name: { value: y } } } ] } } } ``` -------------------------------- ### Apply ESQL Query Options within LINQ Chain Source: https://github.com/elastic/elasticsearch-net/blob/main/docs/reference/linq-to-esql.md Apply ESQL query options directly within the LINQ query chain using the WithOptions method. This offers an alternative to passing options as a separate parameter. ```csharp using Elastic.Clients.Elasticsearch.Esql; var options = new EsqlQueryOptions { Filter = new TermQuery { Field = "environment", Value = "production" }, TimeZone = "Europe/Berlin", AllowPartialResults = true, DropNullColumns = true }; var results = client.Esql.Query(q => q .Where(p => p.InStock) .WithOptions(options) ); ```