ElasticWrapper.ElasticSearch 10.0.0

dotnet add package ElasticWrapper.ElasticSearch --version 10.0.0
                    
NuGet\Install-Package ElasticWrapper.ElasticSearch -Version 10.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ElasticWrapper.ElasticSearch" Version="10.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ElasticWrapper.ElasticSearch" Version="10.0.0" />
                    
Directory.Packages.props
<PackageReference Include="ElasticWrapper.ElasticSearch" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ElasticWrapper.ElasticSearch --version 10.0.0
                    
#r "nuget: ElasticWrapper.ElasticSearch, 10.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ElasticWrapper.ElasticSearch@10.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ElasticWrapper.ElasticSearch&version=10.0.0
                    
Install as a Cake Addin
#tool nuget:?package=ElasticWrapper.ElasticSearch&version=10.0.0
                    
Install as a Cake Tool

ElasticWrapper.ElasticSearch

NuGet .NET Elasticsearch License: MIT

A powerful and flexible .NET wrapper library for Elasticsearch that simplifies the integration and usage of Elasticsearch in .NET applications. This library provides an abstraction layer over the official Elastic.Clients.Elasticsearch client with additional features and conveniences for common Elasticsearch operations.

✨ Features

  • πŸ”Œ Built on top of the official Elastic.Clients.Elasticsearch client (v9.x)
  • πŸ“¦ Simplified repository pattern for Elasticsearch operations
  • πŸ” Built-in request builder for complex query construction
  • πŸ”„ Automatic retry policies using Polly
  • πŸ›‘οΈ Type-safe query building
  • 🧩 Extension methods for common operations
  • 🏷️ Attribute-based configuration
  • πŸ—ΊοΈ Flexible model mapping
  • ☁️ Support for both single-node and Elastic Cloud deployments
  • πŸ“Š Aggregation support with automatic result parsing

πŸ“‹ Prerequisites

  • .NET 10.0 or later
  • Elasticsearch 8.x / 9.x (compatible with Elastic.Clients.Elasticsearch 9.2.2)

πŸ“¦ Installation

Install via NuGet Package Manager:

Install-Package ElasticWrapper.ElasticSearch

Or via .NET CLI:

dotnet add package ElasticWrapper.ElasticSearch

πŸš€ Quick Start

1. Define your entity

public class Product : ElasticEntity<Guid>
{
    public string Name { get; set; } = string.Empty;
    public string Description { get; set; } = string.Empty;
    public decimal Price { get; set; }
    
    [ElasticAggregate]
    public string Category { get; set; } = string.Empty;
}

2. Define your filter

public class ProductFilter
{
    public string? Name { get; set; }
    public List<string>? Categories { get; set; }
    public ElasticRangeFilter? PriceRange { get; set; }
}

3. Configure services

builder.Services.AddElasticWrapper<Product, ProductFilter, Guid>(options =>
{
    options.Uri = "http://localhost:9200";
    options.Index = "products";
});

4. Use the repository

public class ProductService
{
    private readonly ElasticBaseRepository<Product, ProductFilter, Guid> _repository;

    public ProductService(ElasticBaseRepository<Product, ProductFilter, Guid> repository)
    {
        _repository = repository;
    }

    public async Task<Product?> GetByIdAsync(Guid id) 
        => await _repository.GetAsync(id);

    public async Task CreateAsync(Product product) 
        => await _repository.InsertAsync(product);
}

πŸ“š Dependencies

Package Version
Elastic.Clients.Elasticsearch 9.2.2
Polly 8.6.5
Microsoft.Extensions.Hosting.Abstractions 10.0.0
Microsoft.Extensions.Logging.Abstractions 10.0.0
System.ComponentModel.Annotations 5.0.0

βš™οΈ Configuration Options

The ElasticOptions class provides various configuration settings:

Connection Settings

Property Description Required
Uri Elasticsearch server URL (e.g., http://localhost:9200) Yes*
CloudId Elastic Cloud deployment ID Yes*
UserName Username for authentication No
Password Password for authentication No

*Either Uri or CloudId is required.

Index Settings

Property Description Default
Index Default index name Required
UseRollOverAlias Enable index rollover false
Pattern Index pattern for rollover null
MaxSizeGb Max size before rollover 10
MaxDocuments Max documents before rollover null
MaxInnerResultWindow Max inner hit results 1000

Example: Full Configuration

services.AddElasticWrapper<MyEntity, MyFilters, Guid>(options =>
{
    // Basic Settings
    options.Uri = "http://localhost:9200";
    options.Index = "my-application";
    
    // Authentication (if needed)
    options.UserName = "elastic";
    options.Password = "your-secure-password";
    
    // Index Management
    options.UseRollOverAlias = true;
    options.Pattern = "my-application"; // Results in indices like my-application-000001
    options.MaxSizeGb = 5;
    options.MaxDocuments = 1000000;
    
    // Performance Settings
    options.MaxInnerResultWindow = 2000;
    
    // Logging
    options.LogsPath = "logs/elasticsearch";
});

Example: Elastic Cloud Configuration

For Elastic Cloud deployments:

services.AddElasticWrapper<MyEntity, MyFilters, Guid>(options =>
{
    options.CloudId = "deployment:your-cloud-id";
    options.UserName = "elastic";
    options.Password = "your-cloud-password";
    options.Index = "my-cloud-application";
});

πŸ“ Project Structure

ElasticWrapper.ElasticSearch/
β”œβ”€β”€ Attributes/           # Custom attributes for configuration
β”‚   β”œβ”€β”€ ElasticAggregateAttribute.cs
β”‚   β”œβ”€β”€ ElasticIgnoreOnBuildQueryAttribute.cs
β”‚   └── NestedAttribute.cs
β”œβ”€β”€ Base/                  # Core functionality classes
β”‚   β”œβ”€β”€ ElasticBaseRepository.cs
β”‚   β”œβ”€β”€ ElasticClientProvider.cs
β”‚   └── ElasticRequestBuilder.cs
β”œβ”€β”€ Converters/          # Type converters and serialization
β”‚   └── ElasticJsonConverter.cs
β”œβ”€β”€ Extensions/          # Extension methods
β”‚   β”œβ”€β”€ ServiceCollectionExtensions.cs
β”‚   └── StringExtensions.cs
β”œβ”€β”€ Models/              # Data models and DTOs
β”‚   β”œβ”€β”€ ElasticAggregateResult.cs
β”‚   β”œβ”€β”€ ElasticDocumentProperty.cs
β”‚   β”œβ”€β”€ ElasticEntity.cs
β”‚   β”œβ”€β”€ ElasticPaging.cs
β”‚   └── ElasticRangeFilter.cs
└── Options/             # Configuration options
    └── ElasticOptions.cs

🧱 Key Components

ElasticBaseRepository<TEntity, TFilters, TKey>

The base repository class providing common operations:

Category Methods
Cluster HealthAsync
Index IndicesExistsAsync, CreateIndiceAsync, DeleteIndiceAsync, IndicesSizeAsync, IndicesStatsAsync
Documents GetAsync, InsertAsync, UpdateAsync, UpdatePartialAsync, DeleteAsync, ExistsAsync
Search SearchAsync, CountAsync, AnyAsync, GetAggregationsAsync
Bulk BulkInsertAsync, BulkUpdateAsync, BulkDeleteAsync

ElasticRequestBuilder<TEntity, TFilters>

A fluent builder for constructing Elasticsearch queries:

  • Query Types: Bool queries, terms, range, query string, nested
  • Automatic Field Mapping: Converts property names to camelCase
  • Aggregations: Terms, min, max, avg, nested aggregations
  • Sorting: Field sorting with nested path support
  • Pagination: Size and from parameters

ElasticClientProvider<TEntity>

Manages Elasticsearch client configuration:

  • Client initialization with ElasticsearchClient (v9.x)
  • Single-node and Elastic Cloud support
  • Basic authentication
  • Debug mode with request/response logging
  • Configurable request timeout

ElasticEntity<TKey>

Base entity class for Elasticsearch documents:

// Use default Guid key
public class MyDocument : ElasticEntity { }

// Or specify custom key type
public class MyDocument : ElasticEntity<int> { }

🏷️ Custom Attributes

Attribute Description Example
[ElasticAggregate] Mark property for aggregation [ElasticAggregate] public string Category { get; set; }
[ElasticAggregate("groupField")] Aggregate with custom group [ElasticAggregate("category.keyword")]
[ElasticIgnoreOnBuildQuery] Exclude from query building [ElasticIgnoreOnBuildQuery] public string InternalField { get; set; }
[Nested] Map to nested Elasticsearch field [Nested("items")] public List<Item> Items { get; set; }

πŸ“– Usage Examples

Basic CRUD Operations

// Create
await _repository.InsertAsync(new Product { Id = Guid.NewGuid(), Name = "Widget" });

// Read
var product = await _repository.GetAsync(productId);

// Update
product.Name = "Updated Widget";
await _repository.UpdateAsync(product.Id, product);

// Partial Update
await _repository.UpdatePartialAsync(productId, new { Name = "Partial Update" });

// Delete
await _repository.DeleteAsync(productId);

Search with Filters

var filter = new ProductFilter
{
    Name = "widget",
    Categories = new List<string> { "Electronics", "Gadgets" },
    PriceRange = new ElasticRangeFilter { Min = 10, Max = 100 }
};

var paging = new ElasticPaging
{
    From = 0,
    Size = 20,
    SortBy = "Price",
    Descending = false
};

var results = await _repository.SearchAsync(filter, paging);

foreach (var hit in results.Documents)
{
    Console.WriteLine($"{hit.Name}: ${hit.Price}");
}

Aggregations

// Get aggregations based on [ElasticAggregate] attributes
var aggregations = await _repository.GetAggregationsAsync(filter);

foreach (var agg in aggregations)
{
    Console.WriteLine($"Aggregation: {agg.Key}");
    foreach (var option in agg.Options)
    {
        Console.WriteLine($"  {option.Key}: {option.Count}");
    }
}

Bulk Operations

var products = Enumerable.Range(1, 10000)
    .Select(i => new Product { Id = Guid.NewGuid(), Name = $"Product {i}" });

// Bulk insert with automatic chunking
await _repository.BulkInsertAsync(products);

// Bulk update
await _repository.BulkUpdateAsync(updatedProducts);

// Bulk delete
await _repository.BulkDeleteAsync(new[] { 1, 2, 3, 4, 5 });

Index Management

// Check if index exists
if (!await _repository.IndicesExistsAsync())
{
    await _repository.CreateIndiceAsync();
}

// Get index statistics
var stats = await _repository.IndicesStatsAsync();
Console.WriteLine($"Documents: {stats?.Docs?.Count}");
Console.WriteLine($"Size: {stats?.Store?.SizeInBytes} bytes");

// Check cluster health
var health = await _repository.HealthAsync();
Console.WriteLine($"Status: {health.Status}");

πŸ”„ Migration from NEST

This library has been migrated from NEST to the official Elastic.Clients.Elasticsearch client.

Key Changes

NEST (v7.x) Elastic.Clients.Elasticsearch (v9.x)
ElasticClient ElasticsearchClient
ConnectionSettings ElasticsearchClientSettings
response.IsValid response.IsValidResponse
Nest namespace Elastic.Clients.Elasticsearch
Newtonsoft.Json System.Text.Json

Namespace Changes

// Before (NEST)
using Nest;

// After (Elastic.Clients.Elasticsearch)
using Elastic.Clients.Elasticsearch;
using Elastic.Clients.Elasticsearch.QueryDsl;
using Elastic.Clients.Elasticsearch.Aggregations;

πŸ”§ CI/CD

This project uses GitHub Actions for continuous integration and deployment.

Build Workflow

Triggers: Push to main, Pull requests, Manual

Step Action
βœ… Build solution
βœ… Run unit tests
βœ… Create NuGet package
βœ… Upload artifact

Release Workflow

Trigger: Release publication

Step Action
βœ… Build with release version
βœ… Run tests
βœ… Publish to NuGet.org

Creating a Release

# 1. Tag your release
git tag v1.0.0
git push origin v1.0.0

# 2. Create release on GitHub
# 3. Publish - workflow auto-deploys to NuGet

Note: Requires NUGET_API_KEY in repository secrets.

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ’¬ Support

For support and questions, please open an issue in the GitHub repository.


Made with ❀️ by Nuno ARAUJO

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
10.0.0 194 12/4/2025
8.0.400 2,511 3/10/2025