Nera.Lib.Elasticsearch
1.0.2
dotnet add package Nera.Lib.Elasticsearch --version 1.0.2
NuGet\Install-Package Nera.Lib.Elasticsearch -Version 1.0.2
<PackageReference Include="Nera.Lib.Elasticsearch" Version="1.0.2" />
<PackageVersion Include="Nera.Lib.Elasticsearch" Version="1.0.2" />
<PackageReference Include="Nera.Lib.Elasticsearch" />
paket add Nera.Lib.Elasticsearch --version 1.0.2
#r "nuget: Nera.Lib.Elasticsearch, 1.0.2"
#:package Nera.Lib.Elasticsearch@1.0.2
#addin nuget:?package=Nera.Lib.Elasticsearch&version=1.0.2
#tool nuget:?package=Nera.Lib.Elasticsearch&version=1.0.2
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.9)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.9)
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.9)
- Microsoft.Extensions.Options (>= 9.0.9)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 9.0.9)
- Nera.Lib.Database (>= 1.0.10)
- 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.