Ti-Soft.SearchEngine 2.0.1

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

Ti-Soft.SearchEngine

Библиотека для организации нечёткого и фонетического поиска по строкам БД на русском языке.

Она предназначена не для полнотекстового поиска по произвольным документам, а для поиска по строковым полям:

  • названия товаров;
  • описания процессов;
  • фамилии, имена и другие ФИО;
  • артикулы, коды и смешанные текстовые поля;
  • любые другие строковые значения, которые уже лежат в БД.

Основная цель библиотеки — находить нужные записи даже тогда, когда пользователь:

  • допускает опечатки;
  • нажимает соседние клавиши;
  • пишет «как слышит»;
  • не знает точного написания фамилии или слова.

Позиционирование

Ti-Soft.SearchEngine — это не замена Elasticsearch, Lucene.NET, Azure AI Search или другим большим поисковым платформам.

Библиотека решает более узкую прикладную задачу: быстрый локальный поиск по строковым значениям, которые уже загружены из БД или другого источника данных.

Она подходит для сценариев, где нужен поиск по:

  • названиям товаров;
  • коротким описаниям;
  • ФИО;
  • артикулам;
  • кодам;
  • справочникам;
  • смешанным строковым полям.

Библиотека особенно полезна, когда Elasticsearch, Lucene.NET или отдельный поисковый сервис избыточны, а приложению нужен простой встроенный поиск без отдельной инфраструктуры.

Подходящие сценарии:

  • desktop-приложения;
  • малые и средние веб-приложения;
  • внутренние CRM/ERP-модули;
  • админки;
  • локальный и offline-поиск;
  • поиск по справочникам;
  • поиск по ФИО и русским фамилиям.

Библиотека не предназначена для:

  • индексации больших документов;
  • поиска по PDF, HTML и вложениям;
  • распределённых индексов;
  • кластеризации;
  • аналитических запросов;
  • vector search;
  • сложного query language;
  • замены Elasticsearch в high-load production-сценариях.

Главная идея библиотеки — дать .NET-разработчику простой NuGet-пакет для прикладного поиска там, где полноценная поисковая платформа была бы лишней.

Поддерживаемые платформы

Библиотека таргетирует:

  • net6.0
  • net7.0
  • net8.0
  • net9.0
  • net10.0

Установка

После публикации пакета:

dotnet add package Ti-Soft.SearchEngine --version 2.0.1

Быстрый старт

Подготовка данных

using SearchEngine;

public sealed record Product : ISourceData<int>
{
    public int Id { get; init; }
    public required string Text { get; init; }
}

Подготовка индекса и поиск

using SearchEngine;

List<Product> products =
[
    new() { Id = 1, Text = "Красный велосипед" },
    new() { Id = 2, Text = "Согласование договора" },
    new() { Id = 3, Text = "Иванов Сергей Петрович" }
];

Search<int> search = new();

var prepareResult = await search.PrepareIndexResult(products);
if (prepareResult.IsFailure)
{
    Console.WriteLine($"{prepareResult.Error.Code}: {prepareResult.Error.Message}");
    return;
}

var result = search.FindResult(
    "согласование договра",
    new SearchRequest
    {
        MatchMode = QueryMatchMode.SoftAllTerms,
        SearchType = SearchType.NearSearch,
        SearchLocation = SearchLocation.BeginWord,
        AcceptableCountMisprint = 1
    });

if (result.IsFailure)
{
    Console.WriteLine($"{result.Error.Code}: {result.Error.Message}");
    return;
}

foreach (var bucket in result.Value.Items)
{
    Console.WriteLine($"Ранг/дистанция: {bucket.Key}");

    foreach (var id in bucket.Value.Items)
    {
        Console.WriteLine($"  Id: {id}");
    }
}

Что нового в 2.0.1

Версия 2.0.1 — patch-релиз.

Исправлено распознавание русских фамилий в латинской записи для фонетического поиска.

Добавлены regression-тесты для вариантов:

  • Papandopulo;
  • Papondopulo.

Оба варианта теперь корректно находятся при поиске по фамилии Папандопуло.

Что нового в 2.0.0

Версия 2.0.0 — major-релиз.

Основные изменения:

  • основной production API переведён на Result-based контракт;
  • для индексации используется PrepareIndexResult(...);
  • для поиска используется FindResult(...);
  • ожидаемые прикладные ошибки возвращаются как значение, а не через исключения;
  • фонетический поиск по умолчанию переведён на BMPM-подобный алгоритм;
  • MetaPhone убран из production-пути;
  • добавлена поддержка русских фамилий в латинской транслитерации.

Новые интеграции следует строить на PrepareIndexResult(...) и FindResult(...).

API библиотеки

Для подготовки индекса и выполнения поиска используйте:

  • PrepareIndexResult(...)
  • FindResult(...)

Оба метода возвращают типизированный результат выполнения и не выбрасывают исключения в ожидаемых прикладных сценариях.

PrepareIndexResult(...) подготавливает поисковый индекс и возвращает ошибку, если входные данные некорректны или индекс не удалось построить.

FindResult(...) выполняет поиск по подготовленному индексу и возвращает либо результат поиска, либо описание ошибки выполнения.

Ошибки

Для API библиотеки используются:

  • SearchError
  • SearchErrorCode

Это позволяет различать:

  • ошибки входных данных;
  • ошибки индексации;
  • ошибки выполнения поиска;
  • некорректные параметры запроса.

Режимы поиска

AllTerms

Строгий режим.

Все слова запроса должны найтись в записи. Это поведение удобно для большинства бизнес-сценариев, когда пользователь вводит несколько ключевых слов и ожидает именно пересечение по ним.

AnyTerm

Мягкое объединение по словам.

Достаточно совпадения по любому слову запроса. Подходит для широкого поиска и автодополнения.

SoftAllTerms

Гибридный режим.

Сначала выше ранжируются записи, где нашлось больше слов запроса. Внутри одной группы результаты дополнительно ранжируются по суммарной дистанции. Если полных совпадений нет, возвращаются частичные.

Типы поиска

SearchType.ExactSearch

Точный поиск без допуска опечаток.

SearchType.NearSearch

Неточный поиск с учётом опечаток и близких клавиш.

Место поиска

SearchLocation.BeginWord

Поиск только с начала слова.

SearchLocation.InWord

Поиск внутри слова, включая начало.

Фонетический поиск

Для поиска фамилий и похожих имён можно использовать фонетический режим:

using SearchEngine;

public sealed record Person : ISourceData<int>
{
    public int Id { get; init; }
    public required string Text { get; init; }
}

Search<int> search = new(isPhoneticSearch: true);

var prepareResult = await search.PrepareIndexResult(
[
    new Person { Id = 1, Text = "Иванов" },
    new Person { Id = 2, Text = "Папандопуло" },
    new Person { Id = 3, Text = "Терентьев" }
]);

if (prepareResult.IsFailure)
{
    Console.WriteLine($"{prepareResult.Error.Code}: {prepareResult.Error.Message}");
    return;
}

var result = search.FindResult("Папондопуло");

Фонетический поиск по умолчанию использует внутренний BMPM-подобный кодировщик для русских имён и фамилий. Он рассчитан на сценарии, когда пользователь пишет фамилию «на слух» или вводит русскую фамилию в латинской транслитерации.

Примеры поддерживаемого поведения:

Папондопуло  → находит Папандопуло
Забабонова   → находит Забабанова
Ivanov       → находит Иванов
Shcherbakov  → сопоставляется с русской кириллической записью

Фонетический режим ориентирован на русские фамилии в кириллице и распространённой латинской транслитерации. Произвольные английские имена и фамилии, например Smith или Johnson, не кодируются как русские фонетические ключи.

Выбор фонетического алгоритма не является частью публичного API. Достаточно включить фонетический режим через:

Search<int> search = new(isPhoneticSearch: true);

Когда использовать библиотеку

Библиотека особенно полезна, если поиск нужен по строкам БД, а не по документам целиком, и если важно:

  • быстро поднять локальный поиск внутри приложения или сервиса;
  • учитывать опечатки пользователя;
  • учитывать фонетические ошибки при вводе фамилий;
  • не падать исключениями в ожидаемых рабочих сценариях.

Текущее состояние API

Библиотека использует Result-based контракт:

  • PrepareIndexResult(...)
  • FindResult(...)

Новые интеграции следует строить только на этих методах.

Параллельное построение индекса

По умолчанию библиотека использует последовательное построение индекса. Это снижает давление на память и уменьшает вероятность пауз GC.

Для серверных и batch-сценариев параллельную индексацию можно включить явно:

await search.PrepareIndexResult(
    source,
    forceParallel: true,
    parallelProcessingThreshold: 0);

Сборка

dotnet build
dotnet test
dotnet pack src/SearchEngine/SearchEngine.csproj -c Release

Лицензия

Проект распространяется по лицензии MIT. Файл LICENSE включается в репозиторий и в NuGet-пакет.

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  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 is compatible.  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
2.0.1 92 5/6/2026
2.0.0 86 5/6/2026
1.2.0 106 4/16/2026

Версия 2.0.1 исправляет распознавание русских фамилий в латинской записи для фонетического поиска.
     Добавлена поддержка вариантов Papandopulo и Papondopulo для поиска фамилии Папандопуло.
     Публичный API не изменён.