Lucent 0.0.3-beta

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

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 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

dotnet add package Lucent

Quick Start

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<IndexWriter>();
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<IndexSearcher>();
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:

using Lucene.Net.Store;
using Lucent.Configuration;

builder.Services.AddLucentIndex();

// Configure to use a file-based directory
builder.Services.Configure<IndexConfiguration>(options =>
    options.Directory = new MMapDirectory(new DirectoryInfo("index")));

Custom Analyzer

Configure a custom analyzer for your index:

using Lucene.Net.Analysis.En;
using Lucent.Configuration;

builder.Services.Configure<IndexConfiguration>(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:

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<IndexConfiguration>("products", options =>
    options.Directory = new MMapDirectory(new DirectoryInfo("products-index")));

builder.Services.Configure<IndexConfiguration>("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<IndexWriter>("products");
var customersWriter = scope.ServiceProvider.GetRequiredKeyedService<IndexWriter>("customers");
var productsSearcher = scope.ServiceProvider.GetRequiredKeyedService<IndexSearcher>("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:

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; }
}

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:

using Lucene.Net.Facet;
using Lucene.Net.Store;
using Lucent.Configuration;

builder.Services.AddLucentIndex();
builder.Services.Configure<IndexConfiguration>(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:

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<IndexWriter>();
using var taxonomyWriter = scope.ServiceProvider.GetRequiredService<ITaxonomyWriter>();
var facetsConfig = scope.ServiceProvider
    .GetRequiredService<IOptions<IndexConfiguration>>().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:

using Lucene.Net.Facet;
using Lucene.Net.Facet.Taxonomy;
using Lucene.Net.Search;

var searcher = scope.ServiceProvider.GetRequiredService<IndexSearcher>();
var taxonomyReader = scope.ServiceProvider.GetRequiredService<TaxonomyReader>();
var facetsConfig = scope.ServiceProvider
    .GetRequiredService<IOptions<IndexConfiguration>>().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:

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.

Working with ASP.NET Core

Integrate Lucent in your ASP.NET Core application:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddLucentIndex();
builder.Services.Configure<IndexConfiguration>(
    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 and submit pull requests to the develop branch.

License

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

Acknowledgments

  • Built on top of the Lucene.NET library
  • Inspired by the simplicity needs not met by existing abstraction layers
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
0.0.3-beta 217 11/3/2025
0.0.2-beta 197 11/2/2025
0.0.1-beta 181 10/16/2025