Nera.Lib.Elasticsearch 1.0.1

dotnet add package Nera.Lib.Elasticsearch --version 1.0.1
                    
NuGet\Install-Package Nera.Lib.Elasticsearch -Version 1.0.1
                    
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="Nera.Lib.Elasticsearch" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Nera.Lib.Elasticsearch" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="Nera.Lib.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 Nera.Lib.Elasticsearch --version 1.0.1
                    
#r "nuget: Nera.Lib.Elasticsearch, 1.0.1"
                    
#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 Nera.Lib.Elasticsearch@1.0.1
                    
#: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=Nera.Lib.Elasticsearch&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=Nera.Lib.Elasticsearch&version=1.0.1
                    
Install as a Cake Tool

Nera.Lib.Elasticsearch

A comprehensive library for Elasticsearch integration in Nera applications, providing advanced search, filtering, pagination, and aggregation capabilities.

Overview

Nera.Lib.Elasticsearch is a powerful library that simplifies working with Elasticsearch in Nera applications. It provides a robust repository pattern implementation with support for advanced search features, including full-text search, filtering, sorting, pagination, highlighting, and aggregations.

Features

  • Full CRUD Operations: Index, update, delete, and retrieve documents
  • Advanced Search: Full-text search with fuzzy matching and highlighting
  • Filtering: Filter by exact match, range, existence, and more
  • Sorting: Sort by multiple fields with custom ordering
  • Pagination: Standard and advanced pagination options
  • Aggregations: Support for terms, date histogram, and range aggregations
  • Geo Search: Search by geographical location and distance
  • Index Management: Create, delete, and refresh indices
  • Error Handling: Comprehensive error handling and logging
  • IReadRepository Integration: Implements the Nera.Lib.Database IReadRepository interface

Installation

Add the Nera.Lib.Elasticsearch package to your project:

dotnet add package Nera.Lib.Elasticsearch

Usage

Basic Setup

// Register services in DI container
services.AddSingleton<ElasticsearchConfiguration>(sp => new ElasticsearchConfiguration
{
    Url = "http://localhost:9200",
    DefaultIndex = "my-index",
    EnableSsl = true,
    Username = "elastic",
    Password = "password"
});

services.AddSingleton<IElasticClient>(sp =>
{
    var config = sp.GetRequiredService<ElasticsearchConfiguration>();
    var settings = new ConnectionSettings(new Uri(config.Url))
        .DefaultIndex(config.DefaultIndex)
        .BasicAuthentication(config.Username, config.Password)
        .EnableDebugMode(config.EnableDebug)
        .RequestTimeout(TimeSpan.FromSeconds(config.TimeoutSeconds));
    
    return new ElasticClient(settings);
});

services.AddScoped<IMyEntityRepository, MyEntityRepository>();

Creating a Repository

public class MyEntityRepository : BaseElasticsearchRepository<MyEntity, Guid>
{
    public MyEntityRepository(
        IElasticClient elasticClient,
        ElasticsearchConfiguration config,
        ILogger<MyEntityRepository> logger)
        : base(elasticClient, config, logger, "my-entities")
    {
    }
    
    // Add custom repository methods here
    public async Task<List<MyEntity>> SearchByCategory(string category, CancellationToken cancellationToken = default)
    {
        var request = new ElasticsearchPaginationRequest
        {
            Page = 1,
            PageSize = 100,
            Filters = new List<FilterCondition>
            {
                new FilterCondition
                {
                    Field = "category",
                    Operator = "eq",
                    Value = category
                }
            }
        };
        
        var result = await GetPagedResultAsync(request, cancellationToken);
        return result.Items.ToList();
    }
}

Basic CRUD Operations

// Index a document
await repository.IndexAsync(entity);

// Get a document by ID
var entity = await repository.GetByIdAsync(id);

// Update a document
entity.Name = "Updated Name";
await repository.UpdateAsync(entity);

// Delete a document
await repository.DeleteAsync(id);

// Check if a document exists
bool exists = await repository.ExistsAsync(id);

Search and Pagination

// Basic search
var request = new ElasticsearchPaginationRequest
{
    Page = 1,
    PageSize = 10,
    SearchTerm = "search term",
    SortBy = "createdAt",
    SortDirection = "desc"
};

var result = await repository.GetPagedResultAsync(request);

// Advanced search with filters
var advancedRequest = new ElasticsearchPaginationRequest
{
    Page = 1,
    PageSize = 10,
    SearchTerm = "search term",
    SearchFields = new[] { "title", "description" },
    Filters = new List<FilterCondition>
    {
        new FilterCondition
        {
            Field = "category",
            Operator = "eq",
            Value = "electronics"
        },
        new FilterCondition
        {
            Field = "price",
            Operator = "gte",
            Value = 100
        }
    },
    DateRange = new DateRangeFilter
    {
        Field = "publishedDate",
        From = DateTime.UtcNow.AddMonths(-1),
        To = DateTime.UtcNow
    },
    EnableHighlighting = true,
    HighlightFields = new[] { "title", "description" },
    EnableAggregations = true,
    Aggregations = new List<AggregationDefinition>
    {
        new AggregationDefinition
        {
            Name = "categories",
            Type = "terms",
            Field = "category"
        },
        new AggregationDefinition
        {
            Name = "price_ranges",
            Type = "range",
            Field = "price"
        }
    }
};

var advancedResult = await repository.GetPagedResultAsync(advancedRequest);
// Search by location
var locationResult = await repository.SearchByLocationAsync(
    latitude: 40.7128,
    longitude: -74.0060,
    distanceKm: 10,
    page: 1,
    pageSize: 10);

Index Management

// Create an index with settings and mappings
await repository.CreateIndexAsync(i => i
    .Settings(s => s
        .NumberOfShards(3)
        .NumberOfReplicas(1)
        .Analysis(a => a
            .Analyzers(an => an
                .Custom("custom_analyzer", ca => ca
                    .Tokenizer("standard")
                    .Filters("lowercase", "asciifolding")
                )
            )
        )
    )
    .Map<MyEntity>(m => m
        .AutoMap()
        .Properties(p => p
            .Text(t => t.Name(n => n.Title).Analyzer("custom_analyzer"))
            .Text(t => t.Name(n => n.Description).Analyzer("custom_analyzer"))
            .Keyword(k => k.Name(n => n.Category))
            .Number(n => n.Name(n => n.Price).Type(NumberType.Double))
            .Date(d => d.Name(n => n.PublishedDate))
            .GeoPoint(g => g.Name(n => n.Location))
        )
    )
);

// Check if an index exists
bool exists = await repository.IndexExistsAsync();

// Delete an index
await repository.DeleteIndexAsync();

// Refresh an index
await repository.RefreshIndexAsync();

Advanced Usage

Custom Query Building

You can override the query building methods to customize the search behavior:

public class CustomRepository : BaseElasticsearchRepository<MyEntity, Guid>
{
    public CustomRepository(
        IElasticClient elasticClient,
        ElasticsearchConfiguration config,
        ILogger<CustomRepository> logger)
        : base(elasticClient, config, logger, "my-entities")
    {
    }
    
    protected override QueryContainer BuildQueryContainer(QueryContainerDescriptor<MyEntity> queryDescriptor, ElasticsearchPaginationRequest request)
    {
        // Custom query building logic
        var baseQuery = base.BuildQueryContainer(queryDescriptor, request);
        
        // Add additional conditions
        var customQuery = queryDescriptor.Bool(b => b
            .Must(baseQuery)
            .Filter(f => f.Term(t => t.Field("isActive").Value(true)))
        );
        
        return customQuery;
    }
}

Implementing Custom Aggregations

public async Task<Dictionary<string, int>> GetCategoryCounts(CancellationToken cancellationToken = default)
{
    var request = new ElasticsearchPaginationRequest
    {
        Page = 1,
        PageSize = 0, // We only need aggregations, not results
        EnableAggregations = true,
        Aggregations = new List<AggregationDefinition>
        {
            new AggregationDefinition
            {
                Name = "categories",
                Type = "terms",
                Field = "category"
            }
        }
    };
    
    var result = await GetPagedResultAsync(request, cancellationToken);
    
    if (result.Aggregations?.TryGetValue("categories", out var categoriesAgg) == true)
    {
        if (categoriesAgg is IEnumerable<dynamic> categories)
        {
            return categories
                .Select(c => new { Key = c.Key.ToString(), Count = (int)c.Count })
                .ToDictionary(c => c.Key, c => c.Count);
        }
    }
    
    return new Dictionary<string, int>();
}

Configuration Options

The ElasticsearchConfiguration class provides various options to configure the Elasticsearch client:

  • Url: The Elasticsearch server URL
  • Username: Username for authentication
  • Password: Password for authentication
  • DefaultIndex: Default index name
  • EnableSsl: Enable SSL/TLS
  • TimeoutSeconds: Request timeout in seconds
  • MaxRetryAttempts: Maximum retry attempts
  • RetryDelayMs: Retry delay in milliseconds
  • EnableDebug: Enable debug mode
  • DefaultPageSize: Default page size for pagination
  • MaxPageSize: Maximum page size allowed
  • AutoCreateIndex: Enable automatic index creation
  • IndexSettings: Index settings for auto-created indices

Best Practices

  1. Index Naming: Use a consistent naming convention for indices, such as {service}-{entity}-{environment}.
  2. Mapping: Define proper mappings for your entities to ensure optimal search performance.
  3. Pagination: Use reasonable page sizes (10-50) to avoid performance issues.
  4. Caching: Consider caching search results for frequently used queries.
  5. Error Handling: Always handle exceptions from Elasticsearch operations.
  6. Logging: Enable detailed logging during development and debugging.

License

This library is part of the Nera platform and is subject to the same licensing terms as the rest of the platform.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  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
1.0.1 236 9/15/2025
1.0.0 118 9/12/2025