https://github.com/dealloc/lucent
Minimalistic wrapper around Lucene.NET for idiomatic configuration and service management
https://github.com/dealloc/lucent
Last synced: 5 months ago
JSON representation
Minimalistic wrapper around Lucene.NET for idiomatic configuration and service management
- Host: GitHub
- URL: https://github.com/dealloc/lucent
- Owner: dealloc
- License: mit
- Created: 2025-10-15T14:36:00.000Z (8 months ago)
- Default Branch: master
- Last Pushed: 2025-10-16T15:14:13.000Z (8 months ago)
- Last Synced: 2025-10-28T19:47:19.118Z (7 months ago)
- Language: C#
- Homepage: https://lucent.dealloc.be/README.html
- Size: 44.9 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE.md
- Security: SECURITY.md
Awesome Lists containing this project
README
# Lucent
A lean, minimalistic .NET library that provides idiomatic integration of Lucene.NET with dependency injection and modern .NET configuration patterns.
## Overview
Lucent is designed to bring Lucene.NET closer to idiomatic .NET best practices while maintaining direct access to the underlying Lucene.NET types and APIs. Unlike heavier abstraction layers, Lucent focuses on providing just what you need: service container integration, configuration management, and lifecycle handling.
## Key Features
- **Minimal Abstraction**: Direct access to Lucene.NET types and APIs
- **Service Container Integration**: Native support for .NET dependency injection
- **Idiomatic Configuration**: Leverage `IConfiguration` and options patterns
- **Lifecycle Management**: Proper disposal and resource management
- **Lean Design**: No unnecessary wrappers or query builders
## Philosophy
Lucent takes a different approach compared to libraries like Examine. While Examine provides extensive abstractions and query builders, Lucent maintains the full power and flexibility of Lucene.NET while simply making it easier to use in modern .NET applications.
If you require more high-level abstractions, fluent query builders, we recommend checking out the excellent [Examine](https://github.com/Shazwazza/Examine) library.
## Comparison with Examine
| Feature | Lucent | Examine |
|---------|---------|---------|
| Abstraction Level | Minimal | High |
| Query Building | Direct Lucene.NET | Fluent API |
| Learning Curve | Requires Lucene.NET knowledge | Examine-specific |
| Flexibility | Full Lucene.NET power | Limited to abstractions |
| Use Case | Lucene users | Quick implementation |
## Requirements
- .NET 9.0 or later
- Lucene.NET 4.8-beta00017 or later
## Installation
```bash
dotnet add package Lucent
```
## Quick Start
```csharp
using Lucene.Net.Documents;
using Lucene.Net.Documents.Extensions;
using Lucene.Net.Index;
using Lucene.Net.Search;
using Lucent.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
var builder = Host.CreateApplicationBuilder(args);
// Register Lucent index with default configuration (uses RAMDirectory)
builder.Services.AddLucentIndex();
var app = builder.Build();
using var scope = app.Services.CreateScope();
// Get the IndexWriter and add a document
using var writer = scope.ServiceProvider.GetRequiredService();
var document = new Document();
document.AddStringField("name", "brown fox", Field.Store.YES);
writer.AddDocument(document);
writer.Commit();
// Search the index
var searcher = scope.ServiceProvider.GetRequiredService();
var query = new PhraseQuery { new Term("name", "brown fox") };
var hits = searcher.Search(query, 10);
Console.WriteLine($"Hits: {hits.TotalHits}");
```
## Usage
### Basic Index Configuration
By default, Lucent uses an in-memory `RAMDirectory` and `StandardAnalyzer`. For production use, configure a persistent directory:
```csharp
using Lucene.Net.Store;
using Lucent.Configuration;
builder.Services.AddLucentIndex();
// Configure to use a file-based directory
builder.Services.Configure(options =>
options.Directory = new MMapDirectory(new DirectoryInfo("index")));
```
### Custom Analyzer
Configure a custom analyzer for your index:
```csharp
using Lucene.Net.Analysis.En;
using Lucent.Configuration;
builder.Services.Configure(options =>
{
options.Directory = new MMapDirectory(new DirectoryInfo("index"));
options.Analyzer = new EnglishAnalyzer(options.Version);
});
```
### Multiple Indices
Lucent supports registering multiple named indices using keyed services:
```csharp
using Lucene.Net.Index;
using Lucene.Net.Search;
using Microsoft.Extensions.DependencyInjection;
// Register multiple indices
builder.Services.AddNamedLucentIndex("products");
builder.Services.AddNamedLucentIndex("customers");
// Configure each index separately
builder.Services.Configure("products", options =>
options.Directory = new MMapDirectory(new DirectoryInfo("products-index")));
builder.Services.Configure("customers", options =>
options.Directory = new MMapDirectory(new DirectoryInfo("customers-index")));
// Resolve using keyed services
using var scope = app.Services.CreateScope();
var productsWriter = scope.ServiceProvider.GetRequiredKeyedService("products");
var customersWriter = scope.ServiceProvider.GetRequiredKeyedService("customers");
var productsSearcher = scope.ServiceProvider.GetRequiredKeyedService("products");
```
### Available Services
When you call `AddLucentIndex()` or `AddNamedLucentIndex()`, the following services are registered:
- **`IndexWriter`** (scoped) - For adding, updating, and deleting documents
- **`IndexReader`** (scoped) - For reading the index
- **`IndexSearcher`** (scoped) - For searching the index
- **`ITaxonomyWriter`** (scoped) - For writing facet taxonomies (when FacetsDirectory is configured)
- **`TaxonomyReader`** (scoped) - For reading facet taxonomies (when FacetsDirectory is configured)
### Configuration Options
The `IndexConfiguration` class supports the following options:
```csharp
public class IndexConfiguration
{
// The Lucene version to use (default: LUCENE_48)
public LuceneVersion Version { get; set; }
// The directory where the index is stored (default: RAMDirectory)
public Directory Directory { get; set; }
// Optional: The directory for storing facet taxonomies
public Directory FacetsDirectory { get; set; }
// The analyzer to use for text processing (default: StandardAnalyzer)
public Analyzer Analyzer { get; set; }
// Optional: Custom IndexWriterConfig (auto-created if null)
public IndexWriterConfig IndexWriterConfig { get; set; }
// Optional: Configuration for faceted search
public FacetsConfig FacetsConfig { get; set; }
}
```
### Faceted Search
Lucent supports Lucene.NET's faceted search capabilities through taxonomy-based faceting. This enables features like filtering by categories, brands, or other hierarchical dimensions.
#### Basic Facets Setup
Configure facets by setting a `FacetsDirectory` and optionally a `FacetsConfig`:
```csharp
using Lucene.Net.Facet;
using Lucene.Net.Store;
using Lucent.Configuration;
builder.Services.AddLucentIndex();
builder.Services.Configure(options =>
{
options.Directory = new MMapDirectory(new DirectoryInfo("index"));
options.FacetsDirectory = new MMapDirectory(new DirectoryInfo("facets"));
options.FacetsConfig = new FacetsConfig();
});
```
#### Indexing with Facets
When facets are configured, inject `ITaxonomyWriter` along with `IndexWriter`:
```csharp
using Lucene.Net.Documents;
using Lucene.Net.Documents.Extensions;
using Lucene.Net.Facet;
using Lucene.Net.Facet.Taxonomy;
using Lucene.Net.Index;
using var writer = scope.ServiceProvider.GetRequiredService();
using var taxonomyWriter = scope.ServiceProvider.GetRequiredService();
var facetsConfig = scope.ServiceProvider
.GetRequiredService>().Value.FacetsConfig;
var document = new Document();
document.AddStringField("name", "MacBook Pro", Field.Store.YES);
// Add facet fields
document.AddFacetField("category", "Electronics");
document.AddFacetField("brand", "Apple");
// Build the document with facets
var builtDoc = facetsConfig.Build(taxonomyWriter, document);
writer.AddDocument(builtDoc);
writer.Commit();
taxonomyWriter.Commit();
```
#### Searching with Facets
Use `FacetsCollector` and `TaxonomyReader` to retrieve facet counts:
```csharp
using Lucene.Net.Facet;
using Lucene.Net.Facet.Taxonomy;
using Lucene.Net.Search;
var searcher = scope.ServiceProvider.GetRequiredService();
var taxonomyReader = scope.ServiceProvider.GetRequiredService();
var facetsConfig = scope.ServiceProvider
.GetRequiredService>().Value.FacetsConfig;
var query = new MatchAllDocsQuery();
var facetsCollector = new FacetsCollector();
FacetsCollector.Search(searcher, query, 10, facetsCollector);
// Get facet counts
var facets = new FastTaxonomyFacetCounts(taxonomyReader, facetsConfig, facetsCollector);
var categoryFacets = facets.GetTopChildren(10, "category");
foreach (var facet in categoryFacets.LabelValues)
{
Console.WriteLine($"{facet.Label}: {facet.Value}");
}
```
#### Drill-Down Queries
Filter results by facet values using `DrillDownQuery`:
```csharp
using Lucene.Net.Facet;
var drillDownQuery = new DrillDownQuery(facetsConfig);
drillDownQuery.Add("category", "Electronics");
var electronicsCollector = new FacetsCollector();
var topDocs = FacetsCollector.Search(searcher, drillDownQuery, 10, electronicsCollector);
// Get facet counts for the filtered results
var electronicsFacets = new FastTaxonomyFacetCounts(
taxonomyReader, facetsConfig, electronicsCollector);
```
For a complete example, see the [Facets sample](samples/Lucent.Samples.Facets).
### Working with ASP.NET Core
Integrate Lucent in your ASP.NET Core application:
```csharp
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddLucentIndex();
builder.Services.Configure(
builder.Configuration.GetSection("Lucent"));
// In your controllers or services, inject the required Lucene services
public class SearchController : ControllerBase
{
private readonly IndexSearcher _searcher;
public SearchController(IndexSearcher searcher)
{
_searcher = searcher;
}
[HttpGet]
public IActionResult Search(string query)
{
var parsedQuery = new TermQuery(new Term("content", query));
var results = _searcher.Search(parsedQuery, 10);
return Ok(results);
}
}
```
## Contributing
Contributions are welcome! Please read our [contributing guidelines](CONTRIBUTING.md) and submit pull requests to the `develop` branch.
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE.md) file for details.
## Acknowledgments
- Built on top of the [Lucene.NET](https://lucenenet.apache.org/) library
- Inspired by the simplicity needs not met by existing abstraction layers