# Befestigen der Site-Suche nach : PostgreSQL Volltextsuche nach ( und wo es bricht)

<!--category-- ASP.NET, PostgreSQL, Search, RRF -->
<datetime class="hidden">2026-01-14T12:00</datetime>

Die Suche ist eines der Merkmale, die jeder unterschätzt .. . .. Es sieht trivial aus, bis echte Benutzer beginnen, reale Abfragen einzugeben . *konzeptuell* Recht, aber textlich falsch, wenn die Suche in diesen Fällen fehlschlägt, denken die Benutzer nicht, dass die Website kaputt ist.

Es ist auch irgendwie, dass die ' quälte diese Website seit es ' s inception-. [OpenSearch](/blog/textsearchingpt2), , haben auf PostgreSQL Volltextsuche mit ihm gearbeitet ' , Phantasie Vektor-Sache aber war nie wirklich glücklich damit ,. , Nicht dass es stark verwendet ' , fast niemand tut hier , ) , aber es **verwanzt** mich asn vor allem jetzt I'-m Gebäude ein Suchwerkzeug in [***klar*RAG**](https://www.lucidrag.com) Ich dachte, ich sollte es FINALLY beheben.
Ob es IST oder nicht, ist eine andere Angelegenheit.

Dieser Artikel ist ,,''t über den Bau einer Suchmaschine von scratch" ,MSC1 , es ist .''s über die Fixierung der scharfen Kanten des PostgreSQL voll , -" Textsuche in einem realen Produktionssystem , . , I''ll gehen durch die spezifischen Ausfälle Ich traf ,," warum sie passierte , und die pragmatischen Korrekturen erforderlich, um Suche verhalten sich wie Benutzer bereits erwarten , dass ,- , einschließlich Akronym-Handling ?," technische Begriff Parsing , , Phrase search ,, Ausschlusse .

**Aufbauend auf früheren Arbeiten**Dieser Artikel erweitert die [semantische Suchimplementierung](/blog/semantic-search-in-action) die hybride Suche mit reziproken Rank Fusion hinzugefügt -( RRF ,). , Das frühere Artikel deckte die Stiftung , - , die PostgreSQL voll kombinieren , - , Textsuche mit Qdrant Vektor suchen ,. , Dieser Artikel behebt die Randfälle, dass die Implementierung verpasst : , Akronyme, die nicht passen , , technische Begriffe mit speziellen Zeichen , und natürliche Abfragen, dass Postgre SQL ,' , Parser bricht . ,

Die semantische Suchinfrastruktur dient den dualen Zwecken, es macht die Website, ' user,- *und* stellt die Retrieval-Ebene für die [Rechtsanwalt GPT](/blog/building-a-lawyer-gpt-for-your-blog-part1) RAG-System Schreibassistenten, die neue Beiträge mit Hilfe der Website entwirft.''s vorhandene Inhalte als Wissensbasis. Für tiefere Tauchgänge in die zugrunde liegende Technologie siehe [Aufbau eines Rechtsbeistands GPT-", Teil](/blog/building-a-lawyer-gpt-for-your-blog-part3) auf Einbettungen und Vektorsuche

## Die Probleme

### Leere Ergebnisse angezeigt Zufällige Artikel

Wenn eine Suche ergab keine Ergebnisse Das System zeigte zufällige alte Artikel anstelle von hilfreichen Vorschläge Dies verletzt das Prinzip der am wenigsten Überraschung Benutzer erwartet entweder relevante Ergebnisse oder ein klares Spiel gefunden " found message with recent posts as proposes.. , Dies machte es so aussehen, als hätte die Suche funktioniert.

**Die Lösung**Verändert `BlogSearchService.HybridSearchWithPagingAsync()` um zu erkennen, wenn die Suche Null Ergebnisse zurückgibt und wieder auf aktuelle Beiträge nach Datum absteigend angezeigt wird. `NoMatchFound` Flagge bis `BasePagingModel` so kann die Benutzeroberfläche eine entsprechende Nachricht wie -" , keine Übereinstimmung gefunden anzeigen - . , Bedeuteten Sie eines dieser ,?" ,

```csharp
// 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);
}
```

### Akronyme wie z.B. ", DiSE, ", Weren, MKK3, Matching

PostgreSQL-'-Standard Englische Textsuche Konfiguration technisch Indexe Akronyme ., , aber Normalisierung und Beaming machen short ,, , Fall ?- signifikante Begriffe unzuverlässig in der Praxis Wenn Sie nach suchen , " , DiSE , ", , wird es unterlegt zu ," , liese , und dann das englische Wörterbuch kann es wegwerfen oder zuweisen niedriges Gewicht , was Full-- , Textsuche zu verfehlen Artikel, die eindeutig enthalten , die ," ,DiSE .SK12 , im Titel und Inhalt .

**Die Lösung**Akronym-Erkennung hinzugefügt - (.terms Zeichen mit Großbuchstaben -). und Fall--.unsensitive Substring-Fallback mit PostgreSQL.'. `ILIKE`Diese Ergänzungen voll ,-'text Suche anstatt es zu ersetzen , ('see Leistung Überlegungen unten, warum dies akzeptabel ist , um ):'

```csharp
// 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}%"));
```

### Technical Terms with Special Characters Broke Search

Die Suche nach dem genauen Begriff würde bedeuten, dass die Suche nach der exakten Bezeichnung "'t work" .

**Die Lösung**E-Mail-Adresse: http:europa.eu.int `SearchQueryParser` das allgemeine technische Begriffe erkennt und sie mit durchsuchbaren Versionen ersetzt

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

### Fragen wie z.B. ", ASPA.NET und Alpine, ", nicht bearbeitet

PostgreSQL behandelt " und " als Stop-Wort und entfernt es von Suchanfragen . in Kombination mit der Sonderzeichenausgabe , eine natürliche Abfrage wie "ASP ,. ,NET und Alpine , " , würde im Wesentlichen zu einer Suche nach nur . werden.

**Die Lösung**Implementiert einen Google-Abfrageparser im --Stil, der intelligent mit Stoppwörtern umgeht und erweiterte Suchoperatoren unterstützt.

## Die Lösungen

### Google-Dienstleister für die Suche nach Stil

Ich habe eine `SearchQueryParser` Klasse, die Abfragen mit Unterstützung für –: liest

1. **Zitate**: `"exact match"` Suche nach dem genauen Satz
2. **Ausgeschlossene Begriffe**: `-unwanted` Ausgenommen Ergebnisse, die diesen Begriff enthalten
3. **Wildcards**: `ASP*` --Matches für "-ASP-",-Aspnete für ",-"-AsPNetCore-",- usw.
4. **Technische Bedingungen**,: , automatisch handhabt , " , ASPA. , NET", , " , C , #", , usw.

Der Parser verwendet ein kompiliertes Regex-Muster, um die Abfrage zu markieren.

```csharp
[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());
        }
    }
}
```

### Gebäude PostgreSQL tsquery

Der Parser gibt strukturierte Daten aus, die dann in PostgreSQL-'umwandelt werden. `to_tsquery` weil wir -'- strukturierte Syntax erzeugen - nicht `websearch_to_tsquery` weil wir uns bereits geparste Operatoren selbst geben und uns mehr Kontrolle darüber verschaffen, wie Begriffe kombiniert werden

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

> **Warum nicht einfach benutzen `websearch_to_tsquery`?**
> Da es nach wie vor unter technischen Begriffen fehlschlägt, bietet es keine Haken für Hybrid-Ranking oder Fallbacks, indem wir uns selbst analysieren, können wir mit diesen Kantenfällen umgehen, bevor sie PostgreSQL.. erreichen.

### Erweiterte BuildSearchQuery

Das `BuildSearchQuery` Methode wurde komplett neu geschrieben, um die geparste Abfragestruktur zu verwenden. `baseQuery` Filtern Sie bereits nach Sprache, Datumsbereich und Sichtbarkeit.,. Wir fügen search-.spezifische Bedingungen an der Spitze hinzu.

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

## Suchbeispiele

Hier sind einige Beispiele für die verbesserte Suchfunktionalität.

### Grundlegende Suche

```
DiSE
```

Jetzt passend zu Artikeln mit Titel oder Inhalt.(case

### Technische Bedingungen

```
ASP.NET
```

Findet Artikel über ASP ,. ,NET , ( , die automatisch in " , aspnet , " , für Voll-- , Textsuche , ) , umgewandelt werden

### Phrase Suche

```
"semantic search"
```

Findet exakte Phrase ""semantische Suche "" in Artikeln

### Ausgeschlossene Begriffe

```
ASP.NET -Core
```

Nicht enthalten sind Waren der Tarifnr.

### Wildcards

```
ASP*
```

Streichhölzer aus "ASP-",ASPNET-",ASPNetCore-MSC6 usw.

### Komplexe Abfrage

```
"full text search" PostgreSQL -MySQL
```

Findet Artikel mit exaktem Satz.". Volltextsuche.MSC2. UND Erwähnungen von PostgreSQL.,. aber OHNE Artikel, die MySQl erwähnen.

### Vor und nach dem Beispiel

**Abfrage**: `ASP.NET and Alpine`

**Vorher** (, gebrochen, ):,

- ," , ASP-. , NET , " , aufgeteilt in , " , ASP-" , -+ ,-MSC6 , –"
- " und " als Stoppwort entfernt
- Ergebnis: :-Nur sucht nach "-Alpine

**Nach** (-fixiert):

- ,", ASP-.,NET, ", umgewandelt in ", Aspnet, MSC4,
- Intelligent als Teil der Benutzerabfrage-Intent erhalten
- Üblicherweise gesucht
- Ergebnis: :-Fundiert Artikel über sowohl ASP-.-NET und Alpine

## Integration des RRF-Ranking

Die Suche integriert sich mit Reciprocal Rank Fusion, wie in der [frühere semantische Suche Artikel](/blog/semantic-search-in-action#hybrid-search-with-reciprocal-rank-fusion)Hier wird RRF verwendet für *Rangfolge*Es kombiniert bereits die Ergebnisse von BM.25, vollwertige - Textsuche und vektorsemantische Suche

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

Der RRF-Algorithmus verwendet `1/(k+rank)` wo die Ergebnisse aus mehreren Quellen kombiniert werden, dann gelten Boosts für die

- **Kategorie-Match**: +2.0
- **Titelspiel**: +1.0
- **Frische**Exponentieller Zerfall über das Jahr der 1, max.

Für die komplette RRF-Implementierung und wie hybride Suche funktioniert, siehe [Semantische Suche in Aktion](/blog/semantic-search-in-action)Für tiefere Tauchgänge in Einbettungen und Vektor-Ähnlichkeit, siehe [Aufbau eines Rechtsbeistands GPT-", Teil](/blog/building-a-lawyer-gpt-for-your-blog-part3)Die gleiche Infrastruktur ermöglicht sowohl die Suche des Benutzers als auch den RAG-Retrieval für das Schreiben von AI--.

## Technische Architektur

### Abhängigkeitsinjektion

Die neuen Komponenten sind als Dienstleistungen registriert

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

`SearchQueryParser` und `SearchRanker` sind Singletons, weil sie stateless sind, ,, Thread, -,safe, MSC3 und über Anfragen wiederverwendet werden können. `BlogSearchService` ist scoped, weil es auf den Datenbankkontext zugreift.

### Abfragefluss

1. **Benutzer Eingabe der Suchanfrage** Suchcontroller
2. **Abfrageparsierung** SearchQueryParser zerlegt sich in strukturierte Komponenten
3. **Semantische Suche, falls aktiviert** Qdrant-Vektordatenbank mit ONNX-Einbettungen
4. **PostgreSQL Full---Textsuche Immer verfügbar** Schlüsselwort-Matching auf der Grundlage von M→
5. **RRF Fusion** Verbindet beide Ergebnissätze mit der Kategorie
6. **Keine Ergebnisse** Gibt aktuelle Beiträge als Vorschläge zurück

Dieselbe semantische Suchkomponente wird auch von der [Rechtsanwalt GPT](/blog/building-a-lawyer-gpt-for-your-blog-part1) System zum Abrufen relevanter vergangener Blog-Posts für AI---unterstütztes Schreiben. [Teil](/blog/building-a-lawyer-gpt-for-your-blog-part4) für Details über die Aufnahme Pipeline

### Datenbankschema

Suche stützt sich auf eine vorberechnete `SearchVector` Spalte in der `BlogPosts` Tabelle ,:'

```sql
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");
```

Der GIN-Index bietet eine schnelle Volltextsuche über große Textkorpus

## Leistungsbeurteilungen

### Warum ILIKE für Akronyme?

Während `ILIKE` (-case---unempfindlich LIKE-MSC2- ist langsamer als Volltextsuche ,-'-s, die für Akronyme notwendig ist, weil -:-

1. Volltextsuche normalisiert die Terme der / und bricht kurze Großbuchstaben
2. Akronyme sind typischerweise kurze Zeichen, die den Leistungseffekt begrenzen.
3. Die Bedingung wird nur hinzugefügt, wenn nötig.

Dieser Ansatz würde nicht auf willkürliche Substring-Suche über Millionen von Zeilen zu skalieren.

### PostgreSQL Cover Density Ranking`ts_rank_cd`)

PostgreSQL bietet zwei Ranking-Funktionen für die volle --Textsuche an

- `ts_rank`Grundbegriff Frequenz Wie oft werden Begriffe angezeigt?
- `ts_rank_cd`Cover-Dichte-Ranking - Wie nahe Begriffe zusammen erscheinen - )

Wir benutzen `ts_rank_cd` weil es **BM-25--ähnliche Relevanz** durch Berücksichtigung des Begriffs Nähe

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

**Warum? `ts_rank_cd` ist überlegen.**

|, Metrisch | `ts_rank` | `ts_rank_cd` |
|--------|-----------|--------------|
| **Algorithmus** Bedeckungsdichte Bestrahlungsdichte
| **Mehrsprachige Suchanfragen** Belohnte Begriffe, die zusammen erscheinen
| **Beispiel: :-Dockercontainer** Artikel mit ".Docker".50. mal punktet hoch |. Artikel mit Containern von ".". zusammen Punkte höher |.
| **Leistung** Schnelles, Marges langsameres und immer noch nutzendes GIN-Index
| **Verhalten** Einfache Zählung von BM-25

Das ist ein **schnelle Win-Optimierung** Bessere Relevanz Ranking mit Null-Anwendung.- level computation... Alle Rangfolge geschieht in PostgreSQL unter Verwendung des vorhandenen GIN Index auf `SearchVector`.

**Literaturhinweise**

- [PostgreSQL-Dokumentation](https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-RANKING)
- [EF Core RankCoverDensity](https://learn.microsoft.com/en-us/ef/core/providers/postgres/misc#full-text-search)

### Zusätzliche Leistungsoptimierungen

Über die Fixierung der Suchfunktionalitäten hinaus Mehrere wichtige Optimierungen verbessern die Leistung

#### Sprachen-Caching

Verfügbare Sprachen ändern sich selten, wurden aber bei jeder Suchanfrage abgefragt.

```csharp
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);
```

**Auswirkungen**Beseitigt die Datenbankabfrage pro Suchanfrage

#### Ausgefeilte ILIKE-Abfragen

Ursprünglich verwendeter Code `foreach` Schleifen, die mehrere WHERE-Klauseln erzeugen... Jetzt in einzelne Ausdrücke gestapelt...

```csharp
// 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}%")));
}
```

**Auswirkungen**:-Reiniger SQL-,-Reinker schneller für Multi---term-Abfragen

#### Covering Index für häufige Anfragen

Teilindex mit INCLUDE-Spalten für häufige Zugriffsmuster hinzugefügt

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

**Auswirkungen**Ermöglicht [Nur Scans](https://www.postgresql.org/docs/current/indexes-index-only-scans.html) Mehr erfahren PostgreSQL doesns - ' Kein Zugriff auf den Tisch-Hape - , - Reduzierung von I/.O durch 20-30% für häufige Abfragen

#### Unnötig entfernt Beinhaltet

EF Core-'-s `Include()` lädt vollständige Navigation Entities ,. , entfernt, wo nur Navigationseigenschaften verwendet in WO Klauseln , : ,

```csharp
// 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")
```

**Auswirkungen**Weniger Daten aus der Datenbank übertragen

**Literaturhinweise**

- [PostgreSQL-Indexe](https://www.postgresql.org/docs/current/indexes.html)
- [EF Kernleistung](https://learn.microsoft.com/en-us/ef/core/performance/)

### Abfrage-Optimierungsstrategie

Suche baut WO Klauseln schrittweise mit [EF Core®'s Ausdruck Baumzusammensetzung](https://learn.microsoft.com/en-us/ef/core/querying/):

```csharp
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(...); }
```

Dies erzeugt eine **einzelne optimierte SQL-Abfrage** anstatt mehrere Rundfahrten ,. , PostgreSQL , ' s Query Planer kann Statistiken und Indexe effektiv verwenden, wenn es die komplette WHERE Klausel sieht

## Leistungsübersicht

Kumulative Wirkung aller Optimierungen

Optimierung des Latency Impact-Effekts der DB-Lastwirkung von |
|-------------|----------------|----------------|
Sprach-Caching - Minimale Abfrage-Anfrage-Anfragen-Anfrage
Entferne auch (), um | und -5-10% einzuschließen Weniger Datenübertragung
BATCH ILIKE |BATCH -5-10%BATSCH |A Cleaner SQL
Nur Scans von |
Weitere Informationen: http:europa.eu.int/comm/eurostat.html
|-Cache-Fixierung (-Routenparams)-|-N-/-A Verhindert veraltete Daten

**Erwartete Gesamtverbesserung**: **Schnellere Suche** mit deutlich reduzierter Datenbanklast

## Gelernte Lehren

1. **Don.'.t davon aus, dass die Volltextsuche alles behandelt.**Kantenfälle wie Akronyme und Sonderzeichen benötigen besondere Handhabung.

2. **Mehrere Ansätze kombinieren**Vollständige Textsuche -(BM„25)" semantische Suche („Vektoren )„ Substring-Fallbacks" bieten eine bessere Abdeckung als jede einzelne Methode.

3. **Google gestaltete Nutzererwartungen**Die Unterstützung zitierter Phrasen, Ausschlüsse und Platzhalter macht die Suche natürlich, weil Benutzer bereits mit diesen Operatoren vertraut sind.

4. **Hilfreiche Rückschläge bieten**Wenn die Suche fehlschlägt, wird nichts angezeigt...... und es wird deutlich, dass kein Treffer gefunden wurde.......

5. **Nicht gehackt**Ein korrekter Abfrageparser ist sauberer und wartungsfähiger als eine Reihe von String-Manipulationen.

6. **Leverage PostgreSQL-''s built-'in Ranking**Verwendung `ts_rank_cd` statt `ts_rank` für BM-25--ähnliche Relevanz..-Dichtungsranking betrachtet den Begriff Nähe... einen schnellen Gewinn, der die Ergebnisqualität mit Nullanwendung verbessert...--Levelcode...

7. **Profil vor der Optimierung**Die offensichtlichen Engpässe der "... ..( .-FTS parsing . .) . waren' nicht das wirkliche Problem .,. . - Sprachsuchups . , . exzessive enthält .MS K8 und fehlende Indizes hatten größere Auswirkungen als erwartet .

8. **Batch-Datenbankoperationen**Mehrsprachig `foreach` Schleifen, die getrennt erzeugen WO Klauseln suboptimal SQL®.-Verwendung generieren `Any()` oder `All()` um in einzelne Ausdrücke zu chargen

## Künftige Verbesserungen

Mögliche Verbesserungen für die Zukunft – von Bedenken kategorisiert

**Verbesserungen bei der Retrievalbehandlung**:

- **Fuzzy matching**Lenshtein-Abstand für Typotoleranz
- **Synonyme Erweiterung**Weitere Informationen: http:europa.eu.int/comm/eurostat.html

**Parsing-Erweiterungen**:

- **Kategoriefilterung**: `category:ASP.NET` Betreiber
- **Datumsbereich**: `after:2025-01-01` Betreiber

**Rangfolge der Veredelungen**:

- **Hervorhebung der Ergebnisse**Ausgeglichene Teile des Textes in Ergebnissen anzeigen
- **Klicken Sie durch die Verfolgung**Lernen Sie vom Benutzerverhalten, um das Ranking zu verbessern

**Beobachtungsfähigkeit**:

- **Suchanalyse**Verfolgen Sie populäre Abfragen und fehlgeschlagene Suchanfragen, um Lücken zu identifizieren

## Schlußfolgerung

Hochbau-Fertigungssuche erfordert die Fixierung von Kantenfällen **und** Optimierung der Leistung: . Dieser Artikel umfasste sowohl die Befestigung von PostgreSQL als auch Text-Suchkantengehäusen.(acronyms,. Fachbegriffe, ,. Google--.Style-Betreiber und Implementierung wichtiger Leistungsoptimierungen.MSC9. Batching, ,. `ts_rank_cd`).

Die Umsetzung erreicht **Schnellere Suche** bei gleichzeitiger Reduzierung der Datenbanklast durch – :

- Deckdichte-Ranking`ts_rank_cd`Für eine bessere Relevanz
- Sprache caching eliminiert wiederholte Abfragen
- Batched ILIKE-Ausdrücke für Cleaner SQL
- Abdeckung von Indexen, die nur Scans ermöglichen
- Entfernt unnötige EF Core enthält

Die Schlüssel-Insights... kein einzelner Ansatz behandelt alle Fälle... .... PostgreSQL FTS zeichnet sich durch Keyword Matching aus...,... semantische Suche bearbeitet konzeptionelle Abfragen... und gezielte Fallbacks fangen Randfälle... .... Die saubere Parsingschicht verbindet es mit Bedienern und technischen Begriffen, bevor sie die Suchmaschinen erreichen.....

Die semantische Suchinfrastruktur dient dualen Zwecken.

- **Benutzer-Suche nach -**Kombination von Keyword und semantischem Matching für bessere Ergebnisse
- **RAG-Rückgewinnung**Macht die [Rechtsanwalt GPT](/blog/building-a-lawyer-gpt-for-your-blog-part1) Schreibassistent

**Verwandte Artikel**

- [Semantische Suche in Aktion](/blog/semantic-search-in-action) Grundlagenforschung zur Hybridsuche mit RRF
- [Aufbau eines Rechtsbeistands GPT-", Teil](/blog/building-a-lawyer-gpt-for-your-blog-part3) Einbetten von Vektordatenbanken
- [Aufbau eines Rechtsbeistands GPT-", Teil](/blog/building-a-lawyer-gpt-for-your-blog-part4) Einspeisungs-Pipeline

**Offizielle Dokumentation**

- [PostgreSQL Volltextsuche](https://www.postgresql.org/docs/current/textsearch.html)
- [PostgreSQL-Indexe](https://www.postgresql.org/docs/current/indexes.html)
- [EF Kernleistung](https://learn.microsoft.com/en-us/ef/core/performance/)
- [EF Core Npgsql Anbieter](https://www.npgsql.org/efcore/index.html)

Alle verfügbaren Code in der [Blog' s GitHub Repository](https://github.com/scottgal/mostlylucidweb).