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
<PackageReference Include="Nera.Lib.Elasticsearch" Version="1.0.1" />
<PackageVersion Include="Nera.Lib.Elasticsearch" Version="1.0.1" />
<PackageReference Include="Nera.Lib.Elasticsearch" />
paket add Nera.Lib.Elasticsearch --version 1.0.1
#r "nuget: Nera.Lib.Elasticsearch, 1.0.1"
#:package Nera.Lib.Elasticsearch@1.0.1
#addin nuget:?package=Nera.Lib.Elasticsearch&version=1.0.1
#tool nuget:?package=Nera.Lib.Elasticsearch&version=1.0.1
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);
Geo Search
// 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 URLUsername
: Username for authenticationPassword
: Password for authenticationDefaultIndex
: Default index nameEnableSsl
: Enable SSL/TLSTimeoutSeconds
: Request timeout in secondsMaxRetryAttempts
: Maximum retry attemptsRetryDelayMs
: Retry delay in millisecondsEnableDebug
: Enable debug modeDefaultPageSize
: Default page size for paginationMaxPageSize
: Maximum page size allowedAutoCreateIndex
: Enable automatic index creationIndexSettings
: Index settings for auto-created indices
Best Practices
- Index Naming: Use a consistent naming convention for indices, such as
{service}-{entity}-{environment}
. - Mapping: Define proper mappings for your entities to ensure optimal search performance.
- Pagination: Use reasonable page sizes (10-50) to avoid performance issues.
- Caching: Consider caching search results for frequently used queries.
- Error Handling: Always handle exceptions from Elasticsearch operations.
- 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 | Versions 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. |
-
net9.0
- Microsoft.Extensions.Configuration.Abstractions (>= 9.0.8)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.8)
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.8)
- Microsoft.Extensions.Options (>= 9.0.8)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 9.0.8)
- Nera.Lib.Core (>= 1.0.8)
- Nera.Lib.Database (>= 1.0.1)
- NEST (>= 7.17.5)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.