Back to "Управлення сайтом' пошукиM SK1 Полне застосування PostgreSQL - Текстовий пошук ( і де він руйнуєтьсяMSC4"

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

ASP.NET PostgreSQL RRF Search

Управлення сайтом' пошукиM SK1 Полне застосування PostgreSQL - Текстовий пошук ( і де він руйнуєтьсяMSC4

Wednesday, 14 January 2026

Поиск - одна з тих характеристик, яких недооцінюють усі. . Це виглядає банально, поки реальні користувачі не починають друкувати справжні запитання. концептуально right but textually wrong. When search fails in those cases , users donMSC2t think M SK3edge case" МSK5they think the site is broken

Я подивився на те, Відкрите пошук, працювали над пошуком повного тексту PostgreSQL з ним ' чудові векторні речі, але ніколи не були дійсно щасливі з ним заплутаний я особливо зараз я будую пошуковий інструмент в прозораРАГ я думав, що повинен нарешті це виправити. Чи це так, чи ні - це інша справа.

Ця стаття не про те, як побудувати пошуковий двигун з нуля. МСК1 Це МСК2 про виправлення острих країв повного PostgreSQL. МSK3 пошук текстів у реальному виробничому systemie. . Я МСК5 розглянемо певні недоліки, які я бачив., чому вони трапились? , і прагматичне виправлення, яке необхідно для того, щоб пошук поводився так, як вже очікують користувачі.

Збудування на основі попередньої роботи: Цей artykuł розширює застосування семантичного пошуку що додала гібридну пошукову систему з реципрочною об 'єднанням рангів (RRFM SK1 Те, що раніше описувало основу - поєднання PostgreSQL повного МSK3 текстового пошуку з Qdrant векторним пошуком M SK4 Цей artykuł вирішує крайні випадки, яких Implementation пропустила : акроніми, які не співпадають с МСК6 не співпадають с MСК7 технічні терміни з особливими символами М СК8 і природні питання, які розбиває Parser Postgre SQL M СК9

Семантична пошукова інфраструктура має двоє цілей: МСК0, вона дає доступ до сайту, МСК1, користувача, МSK2 і орієнтується на пошук і надає шар пошуку для Адвокат GPT РАG-система -допомічник, який пише нові записи за допомогою сайту МSK1 наявний контент як база знань МSK2 Для глибших подивів на базову технологію , читайте Збудову " Адвоката ГПЗМSK1 МСК2 Частину МСК3 на вбудовах та векторних пошуках.

Проблеми

1. Empty Results Showed Random Articles

Коли пошук не давав результатів, система показувала випадкові старі статті замість допоміжних підказокМSK1 Це було порушенням принципу найменшого здивування МСК2 користувачі очікували або відповідних результатів, або ж чіткого MСК3 не знаходилось співпадінняМ СК4 повідомлення з останніми постами як підказкиM СК5 Це змусило виглядати так, ніби пошук спрацювало МСК6 просто погано М СК7

Справа: Modiфіковано BlogSearchService.HybridSearchWithPagingAsync() щоб виявити, коли пошук повертає нуль результатів і повертається до показу останніх постів, запорядкованих по даті падіння. Добавлено NoMatchFound прапором до BasePagingModel таким чином інтерфейс може відображати важливе повідомлення, як: "Ненайдено співпадінняM SK1 Ви маєте на увазі одне з цих?"

// No match found - return recent posts as suggestions
if (noMatchFound)
{
    Log.Logger.Information("No search results for '{Query}', returning recent posts as suggestions", query);
    return await GetRecentPostsAsSuggestions(targetLanguage, startDate, endDate, page, pageSize);
}

2. Акроніми на кшталт "DiSEM SK2 Weren't Matching

У стандартній конфігурації пошуків тексту в англійській мові PostgreSQL' акроніми відображаються як акроніми ,, але звичайність та закінчування роблять короткі, випадки - значні терміни ненадійними у практиціM SK4 Коли ви шукаєте MSC5DiSE",, він зводиться до lowercased (нижчі літери) на МSK7diseMNK8 і тоді англійський словник може відкинути його або присвоити маловажливе слово(акронім)Mスク9, що призводить до повного МSK10 пошуку тексту, який пропустить статті, які чітко містять "DiSeMRK12 у назвах та змістіMS13

Справа: Добавлено розпізнавання акронімів | | ( | терміни | МSK2 | символи з верхніми літерами ILIKE. Це додає повного - пошуку тексту, а не замінює його.

// Detect if query looks like an acronym or short term
var isAcronymLike = query.Length <= 6 && query.Any(char.IsUpper);

// Add substring search for acronyms
searchQuery = searchQuery.Where(x =>
    EF.Functions.ILike(x.Title, $"%{acronym}%")
    || EF.Functions.ILike(x.PlainTextContent, $"%{acronym}%"));

3. Технический термін з особливими символами Пошкодило пошук

Поиски на "ASPM SK1NET" або "CMSC4 не спрацюють, тому що в Parserі для текстового пошуку PostgreSQLМSK5 відображають періоди та хеш-символи як делімітаториMスク6 розділяючи МSK7АSPМСК8NET" на \ "\ASP\MСК11\ і \ МСК12\ NET\ MСК13\ як окремі символи. Це означало, що пошук точного терміну не спрацьовує.

Справа: Створили SearchQueryParser що визначає звичайні технічні терміни і замінює їх пошуковими версіями:

private static readonly Dictionary<string, string> TechnicalTerms = new(StringComparer.OrdinalIgnoreCase)
{
    ["asp.net"] = "aspnet",
    ["c#"] = "csharp",
    [".net"] = "dotnet",
    ["f#"] = "fsharp",
    ["node.js"] = "nodejs",
    // ... more terms
};

4. Такі питання, як "ASPM SK2NET and Alpine" Не спрацювало

PostgreSQL сприймає " і " як застереження і виключає їх з пошуку. МSK2 Поєднано з проблемою спеціального символу МSK3 природним запитом, таким як | " | ASP | МSK5 | NET та | Alpine \ " | в основному стане пошуком для |

Справа: Implemented a Google -style query parser that handles stop words intelligently and supports advanced search operators

Рішення

Оператори пошуку Google-Style

Я реалізував SearchQueryParser клас, який аналізує питання з підтримкою для:

  1. Цитовані фрази: "exact match" - шукає точну фразу
  2. Виключені умови: -unwanted - не включає результати, що містять цей термін
  3. Вілдкарти: ASP* - порівнює "ASPM SK2 МSK3АSPNET", "ASPNetCoreMSC6 і т.д.
  4. Технические умови: Автоматичний контроль

Розшифровувач використовує компіліровану модель регекса для символізації запиту:

[GeneratedRegex(@"""([^""]+)""|(-)?(\S+)", RegexOptions.Compiled)]
private static partial Regex QueryTokenRegex();

public ParsedQuery Parse(string query)
{
    var matches = QueryTokenRegex().Matches(processedQuery);

    foreach (Match match in matches)
    {
        // Quoted phrase
        if (match.Groups[1].Success)
        {
            var phrase = match.Groups[1].Value.Trim();
            result.Phrases.Add(phrase);
            continue;
        }

        // Excluded term (starts with -)
        if (match.Groups[2].Success)
        {
            var term = match.Groups[3].Value.Trim();
            result.ExcludeTerms.Add(term.ToLowerInvariant());
            continue;
        }

        // Regular term or wildcard
        var token = match.Groups[3].Value.Trim();
        if (token.Contains('*'))
        {
            result.WildcardTerms.Add(token.Replace("*", ""));
        }
        else if (!StopWords.Contains(token))
        {
            result.IncludeTerms.Add(token.ToLowerInvariant());
        }
    }
}

Збудовування штрих-колей PostgreSQL

Програміст генерує структуровані дані, які потім перетворюються на PostgreSQL to_tsquery тому що ми генеруємо структурований синтакс - не websearch_to_tsquery тому що ми - МСК0 - вже самі розшифровували операторів, - МSK1 - даючи нам більше контролю над тим, як об 'єднуються умови, - .

public string BuildTsQuery(ParsedQuery parsed)
{
    var queryParts = new List<string>();

    // Add include terms with AND
    foreach (var term in parsed.IncludeTerms)
    {
        queryParts.Add(term);
    }

    // Add wildcard terms with :* suffix
    foreach (var term in parsed.WildcardTerms)
    {
        queryParts.Add($"{term}:*");
    }

    return queryParts.Count > 0 ? string.Join(" & ", queryParts) : string.Empty;
}

Чому б не просто використовувати websearch_to_tsquery? Тому що він все ще не працює на технічному рівні, акронімиM SK1 та домені- специфічна синтаксиса MSC3 і не дає ніяких Hakів для гібридного рейтингу чи падінь . Розшифровуючи самих себеMska5 ми можемо обговорити ці крайні випадки перед тим, як вони досягнуть PostgreSQLMска6

Удосконалена пошуковая система BuildSearchQuery

І BuildSearchQuery метод був повністю переписан, щоб використовувати структуру розшифровки запитів. Зауважте, що baseQuery вже відфільтровані по мові, діапазон датиМSK1 і видимість M SK2 ми' ми додаємо пошукMSC4конкретні умови нагорі :

private IOrderedQueryable<BlogPostEntity> BuildSearchQuery(
    string query,
    string language,
    DateTime? startDate,
    DateTime? endDate,
    string order)
{
    var parsed = _queryParser.Parse(query);
    IQueryable<BlogPostEntity> searchQuery = baseQuery;

    // Handle phrases (exact substring matching)
    foreach (var phrase in parsed.Phrases)
    {
        searchQuery = searchQuery.Where(x =>
            EF.Functions.ILike(x.Title, $"%{phrase}%")
            || EF.Functions.ILike(x.PlainTextContent, $"%{phrase}%")
            || x.Categories.Any(c => EF.Functions.ILike(c.Name, $"%{phrase}%")));
    }

    // Build tsquery for include terms and wildcards
    var tsQuery = _queryParser.BuildTsQuery(parsed);

    // Apply full-text search if we have terms
    if (!string.IsNullOrWhiteSpace(tsQuery))
    {
        searchQuery = searchQuery.Where(x =>
            x.SearchVector.Matches(EF.Functions.ToTsQuery("english", tsQuery))
            || x.Categories.Any(c =>
                EF.Functions.ToTsVector("english", c.Name)
                    .Matches(EF.Functions.ToTsQuery("english", tsQuery))));
    }

    // Handle acronyms with case-insensitive substring search
    // This supplements full-text search (additive OR), not replaces it
    var acronymTerms = parsed.IncludeTerms
        .Concat(parsed.WildcardTerms)
        .Where(t => _queryParser.IsAcronymLike(t))
        .ToList();

    foreach (var acronym in acronymTerms)
    {
        searchQuery = searchQuery.Where(x =>
            EF.Functions.ILike(x.Title, $"%{acronym}%")
            || EF.Functions.ILike(x.PlainTextContent, $"%{acronym}%"));
    }

    // Handle excluded terms (must NOT contain these)
    foreach (var excludeTerm in parsed.ExcludeTerms)
    {
        searchQuery = searchQuery.Where(x =>
            !EF.Functions.ILike(x.Title, $"%{excludeTerm}%")
            && !EF.Functions.ILike(x.PlainTextContent, $"%{excludeTerm}%")
            && !x.Categories.Any(c => EF.Functions.ILike(c.Name, $"%{excludeTerm}%")));
    }

    return orderedQuery;
}

Ось приклади пошуку

Ось кілька прикладів покращених пошукових можливостей:

Найпростіший пошук

DiSE

✅ Тепер збігає статті з МSK1DiSEM SK2 в заголовку або змісті

Технические умови

ASP.NET

✅ Знаходить статті про ASPM SK1NET (автоматично конвертоване в МSK3aspnet" для повногоMSC5текстового пошукуMスク6

Поиск фрази

"semantic search"

✅ знаходить точну фразу " пошук семантики МSK2 в статьях

Виключені умови

ASP.NET -Core

✅ знаходить статті ASPM SK1NET, але не включає ті, що згадують "Core"

Вілдкарти

ASP*

✅ Matches МSK1ASPM SK2 "AspNET", "ASPNetCoreMSC6 і т.д.

Складне запитання

"full text search" PostgreSQL -MySQL

✅ знаходить статті з точною фразою " пошук у повному тексті МSK2 І згадки PostgreSQL МSK3, але за винятком статей, які стосуються MySQL

До і після прикладу

Запитання: ASP.NET and Alpine

До (перерванаM SK1

  • МSK0АСП.NETM SK2 поділено на "ASPMSC4 + | | МSK6NET | "
  • " іM SK1 видалено як слово зупинки
  • Результат: Тільки пошуки за M SK1Alpine"

Після (фіксованийM SK1

  • "ASPM SK1NET" конвертоване в "aspnetMSC4
  • " іM SK1 розумно зберігаються як частина задуму користувача
  • "AlpineM SK1 шукали нормально
  • Результат: знаходить статті про ASPM SK1NET та Альпі.

Інтеграція рейтингів РРФ

Поиск інтегрується з об 'єднанням реаквівалентного рангу (RRFM SK1, як вказано в попередній семантичний пошук article. РР тут для рейтинг, не запам 'ятовує МSK1 він вже об' єднує МSK2 отримані результати з BM 25 повний ХМSK4 пошук тексту та векторного семантичного пошуку

// Fuse using RRF with category/freshness boosts
var fusedDtos = _ranker.FuseResults(bm25Results, vectorResults, query);

Алгоритам RRF використовує 1/(k+rank) де k=60 об 'єднує результати з багатьох джерел ,, тоді застосовує підштовхування для МSK2

  • Об 'єднання категорій: +2.0
  • Title match: +1.0
  • Свежість: Eksпоненційне розпадіння протягом МSK1 року МSK2 max )

Для повної implementaції RRF і того, як працює гібридний пошук, читайте Семантичний пошук в дії. Для глибших занурень у вбудова та векторну подібність Збудову " Адвоката ГПЗМSK1 МСК2 Частину МСК3. Схожа інфраструктура дає можливість як для користувача - орієнтуватися на пошук, так і для отримання RAG для штучного інтелекту

Технологічна архітектура

Інгекція залежності

Нові компоненти зареєстровані як послуги:

services.AddSingleton<SearchQueryParser>();
services.AddSingleton<SearchRanker>();
services.AddScoped<BlogSearchService>();

SearchQueryParser і SearchRanker єシングルтонами, тому що вони ' є безладними МSK1 нитка МSK2 безпечні , і можуть бути повторно використані в різних запитах BlogSearchService застосовується, тому що він має доступ до контексту бази даних.

Попитний потік

  1. Пользователь вводить пошуковий запит → Kontrolер пошуку
  2. Розшифрування запитів → SearchQueryParser розділяє на структуровані компоненти
  3. Семантичний пошук ( якщо включеноM SK1 → Qdrant векторна база даних з вбудовами ONNX
  4. PostgreSQL - повний- пошук тексту M SK1 завжди доступний ) → BMM SK1на основі співпадіння ключевих слів
  5. РРФ синтез → Об 'єднує обидві результати з категорієюM SK1швидшення
  6. Ніяких результатів → Возв 'язує останні пости як propozycje

Цей самий семантичний компонент пошуку також використовується Адвокат GPT система, яка відображає важливі минулі блогові записи для штучного інтелекту-авторизоване письмоM SK1 См. Частина 4 для більш детальної інформації про канал запилення.

Карта бази даних

Поиск базується на SearchVector в столбці BlogPosts таблиця:

ALTER TABLE mostlylucid."BlogPosts"
ADD COLUMN "SearchVector" tsvector
GENERATED ALWAYS AS (
    to_tsvector('english',
        coalesce("Title", '') || ' ' ||
        coalesce("PlainTextContent", '')
    )
) STORED;

CREATE INDEX idx_blog_posts_search_vector
ON mostlylucid."BlogPosts"
USING GIN ("SearchVector");

GIN (Ogólnий Індекс Inverted МSK1 надає швидке повнеM SK2 пошук тексту через великі текстові Корпорації.

Рівень ефективності

Чому ILIKE для акронімів?

В той час ILIKE (caseM SK1insensitive LIKE) is slower than full

  1. Полний-текстовий пошук звичайнийМSK1постановлює терміниM SK2 руйнує короткі літери у верхньому рядку
  2. Акроніми, як правило, короткі: (≤6 символи
  3. умова додається лише тоді, коли це необхідно (відмітні акронімиM SK1

Цей підхід не збільшуватиме масштаб до произвольного пошуку підтримками на мільйони рядків - але для цільового зворотнього відхилення акронімів це ' потрібне МSK2

Рейтинг щільності обкладинки PostgreSQL (ts_rank_cd)

PostgreSQL пропонує дві рейтингові функції для повного-текстового пошукуM SK1

  • ts_rank: Початкова частота вираження термінів
  • ts_rank_cd: Рейтинг щільності оболонки ( наскільки близькі умови виглядають разом МSK2

Ми використовуємо ts_rank_cd тому що він надає Різниця між BM25- і з огляду на близькість терміну

// Order by cover density ranking - rewards term proximity
orderedQuery = searchQuery.OrderByDescending(x =>
    x.SearchVector.RankCoverDensity(EF.Functions.ToTsQuery("english", tsQuery)));

Чому? ts_rank_cd superior:

Метрічний МSK1 ts_rank ts_rank_cd
Алгоритм Двічна частота МSK1 щільність покритості МSK2приблизність ) мSK4
Багато-запитів на слова Вираховує умови окремо МSK1 Правила винагороди, які з 'являються разом МSK2
До прикладу: " контейнери для дротівM SK2 Artykuł з МSK1докеромM SK2 МSK3 часто набирає високих балів Artykuł із мSK5доkkerовими контейнерами" разом набирає більше балів
Результати Швидкий Трохи повільніший МSK2 все ще спирається на індекс ГИН МSK3
Подібність Прості підрахунки МSK1 Приблизні дані BM МSK2

Це швидка оптимізація - кращий рейтинг релевантності з нульовим застосуванням -вирахунки рівняM SK2 Всі рейтинги відбуваються в PostgreSQL, використовуючи наявний індекс GIN на SearchVector.

Ссылки:

Додаткові оптимізації ефективності

Окрім відновлення пошукової функції, деякі ключові оптимізації покращують ефективністьM SK1

1. Language Caching

Доступні мови рідко змінюються, але їх запитували на кожному пошуковому запиті.

private static readonly TimeSpan LanguageCacheDuration = TimeSpan.FromHours(1);
private static List<string>? _cachedLanguages;
private static DateTime _languageCacheExpiry = DateTime.MinValue;
private static readonly SemaphoreSlim _cacheLock = new(1, 1);

Вплив: Виключає 1 базу даних для кожного запиту

2. Batched ILIKE Queries

Використовений оригінальний код foreach цикли, що створюють багатоklausників, де застосовуються clauses WHERE. Тепер поєднані в одиниці виразівM SK1

// BEFORE: Multiple WHERE clauses
foreach (var acronym in acronymTerms)
{
    searchQuery = searchQuery.Where(x =>
        EF.Functions.ILike(x.Title, $"%{acronym}%"));
}

// AFTER: Single batched WHERE
if (acronymTerms.Count > 0)
{
    searchQuery = searchQuery.Where(x =>
        acronymTerms.Any(acronym =>
            EF.Functions.ILike(x.Title, $"%{acronym}%")));
}

Вплив: Прозоріший SQL, ~5-10% швидший для wieluM SK3term queriesMSC4

3. Індекс об 'єднання для загальних запитів

Додали частину індексу з колонами INCLUDE для частого доступу:

CREATE INDEX idx_blog_posts_search_covering
ON mostlylucid."BlogPosts" ("LanguageId", "IsHidden", "ScheduledPublishDate")
INCLUDE ("Id", "Slug", "Title", "PublishedDate")
WHERE "IsHidden" = false;

Вплив: Включає indeks- тільки сканує - PostgreSQL не мусить ' мати доступу до табличного купуля МSK2, зменшуючи IM SK3O на МSK4 для поширених запитів

4. Вибрали необов 'язкове, включаючи

Корінь EF's Include() завантаження повних об 'єктів навігації. Виключено, коли тільки ориентації навігуації є використані в пунктах де .

// BEFORE: Loads full LanguageEntity into memory
.Include(x => x.LanguageEntity)
.Where(x => x.LanguageEntity.Name == "en")

// AFTER: EF translates navigation property without loading entity
.Where(x => x.LanguageEntity.Name == "en")

ВпливМSK0 ~5-10% скорочення пам 'яті МSK2 менше даних, передаваних з бази даних .

Ссылки:

Стратегія оптимізації запитів

Поиск будує, де clauses інкрементально використовують Конструкція дерева вираження EF Core':

IQueryable<BlogPostEntity> searchQuery = baseQuery;

// Each filter added conditionally - PostgreSQL optimizes the final query
if (parsed.Phrases.Count > 0) { searchQuery = searchQuery.Where(...); }
if (!string.IsNullOrWhiteSpace(tsQuery)) { searchQuery = searchQuery.Where(...); }
if (acronymTerms.Count > 0) { searchQuery = searchQuery.Where(...); }

Це генерує один оптимізований SQL запрос замість багатого циклу подорожей. PostgreSQL' запланувальник запитів може використовувати статистику та індекси ефективно, коли бачить цілу klauzulę де .

Підсумок результатів

Об 'ємний вплив усіх оптимацій:

МSK0 Оптимізація Вплив на тривалість МSK2 Вказ на завантаження DB
Caching мови МSK1 Minimal МSK2 -1 query/request M
Позбутись У тому числі МSK1 МSK2 ♫ ♫ -5-10% ♫
Batch ILIKE
Індекс коригування МSK1 МSK2 Індексус
МСК0 tsМSK1rank_cd M SK3 Схоже МSK4 Краще співпадіння
Установка в буфері МSK1маршрутні парами МSK2 N мSK4 A M Захищає застарілі дані МСК6

Загалом очікувана покращення: 30-50% швидший пошук з значним зниженням завантаження бази даних.

Уроки, отримані

  1. Не припускайте, що пошук текстів повний: Машини з краями, такі як акроніми та особливі символи, потребують спеціального обробкиM SK1

  2. Об 'єднати кілька підходів: ПолнеM SK1 пошук тексту (BM25) МSK4 семантичний пошук МSK5 векториMSC6 + зворотній відхилення підтримки дає краще покрытие, ніж будь-яка інша методика

  3. Google формує очікування користувачів: підтримка зацитованих речей , винятків M SK2 і wildcards робить пошук природнім, тому що користувачі вже знайомі з цими операторами

  4. Допоможіть відхиленням: Коли пошук зазнає невдачіM SK1 не показує' не показує нічого - показує останні пости і робить зрозуміло, що не було знайдено жодного співпадіння

  5. Розібрати, donM SK1t hack: Правильний розшифровувач запитів є чистішим і більш підтримливим, ніж ряд маніпуляцій струн

  6. Лівержування PostgreSQL'сбудовані-в рейтингі: Використовувати ts_rank_cd замість ts_rank для BM25-подібна значущістьM SK1Рейтинг щільності обкладинки вважає близькість терміну - швидкий перемога, що покращує якість результатів з нульовим застосуванням

  7. Профиль перед оптимізацією: Очевидні " перешкоди МSK3 Цифровий аналізFTS МSK4 не були проблемою, МSK5 не є справжньою проблемою мSK6 пошуки мов M, надмірне включає в себе МСК8 і недосяжні індекси мали більший вплив, ніж очікувалося ммSK9

  8. Операції з базою даних: Множество foreach цикли, що створюють окремі clauses, де генеруються неoptimalні SQL. Usage Any() або All() для поєднання в одиниці виразів.

Дальне покращення

Можні покращення для майбутнього

Поліпшення пошуку:

  • Невизначено співпадіння: Відстань Левенштейна для толерантності до типо
  • Поширення синонимуМSK0 " пост у блогу МSK2 | | → " стаття

Поліпшення аналізу:

  • Фильтрація категорій: category:ASP.NET оператор
  • Відрізок: after:2025-01-01 оператор

Переробка рейтингу:

  • Висвітлення результатів: Показать співпадні частини текста в результатах
  • Щелкніть -за допомогою стеження: Навчитися з поведінки користувача, щоб покращити рейтинг

Обсервабельність:

  • Аналітика пошуку: Прослідкувати популярні питання і невдачі пошуку, щоб визначити прогалини

Завершення

Виготовлення будівельних будівель requires fixing edge cases і оптимізувати продуктивність. Цей artykuł охватив як fixing PostgreSQL full, так і cases of text search edge. (, acronyms, ,, technical terms, МSK5, Google,-, operators of style, ), implementing key performance optimizations. ts_rank_cd).

Втілення досягає 30-50% швидший пошук зменшуючи завантаження бази даних за допомогою:

  • Рейтинг щільності обкладинки (ts_rank_cd) для кращої значущості
  • Языковий кэш, який eliminує повторювані питання
  • Batched ILIKE expressions for cleaner SQL
  • Обгортання індексів, що дозволяє лише сканувати
  • Уявлено, що необов 'язкове ядро EF включає

Найголовніша ідея: жоден єдиний підхід не вирішує всі випадкиM SK1 PostgreSQL FTS чудово працює з співпадінням ключів кліпу , семантичний пошук відповідає за концептуальні питання МSK3 та цільові відхилення охоплюють крайні випадки M SK4 чиста warstwа аналізу об 'єднує їх , об' єднає оператори та технічні терміни перед тим, як вони дістаються до пошукових машин MSC6

Семантична пошукова інфраструктура працює для двох цілей:

  • Пользователь- орієнтується на пошук: Об 'єднує ключові слова та семантичні співпадіння для кращого результату
  • Перехоплення RAG: Мощує Адвокат GPT ассистент

Подібні статті:

офіційна документація:

Весь код доступний в блог's Репозитори GitHub.

logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.