🌐 Detecting your location…

So erstellen Sie im Jahr 2026 eine Volltextsuchfunktion mit PostgreSQL

⏱️6 min read  ·  1,122 words

Durch das Hinzufügen einer Suche zu Ihrer Anwendung greifen Entwickler häufig zu Elasticsearch – PostgreSQL verfügt jedoch über eine leistungsstarke integrierte Volltextsuche, die die meisten Anforderungen ohne zusätzliche Infrastruktur erfüllt. Dieser Leitfaden zeigt, wie Sie eine Produktionssuche mit PostgreSQL erstellen, von den Grundlagen bis hin zu Ranking und Hervorhebung.

Warum PostgreSQL für die Suche verwenden?

  • Keine zusätzliche Infrastruktur: Nutzen Sie Ihre bestehende Datenbank – keine separate Suchmaschine zum Ausführen und Synchronisieren
  • Gut genug für die meisten Apps: Verarbeitet Millionen von Dokumenten mit ordnungsgemäßer Indexierung
  • Transaktionskonsistenz: Durchsuchen Sie Indexaktualisierungen mit Ihren Daten, ohne Synchronisierungsverzögerung
  • Umfangreiche Funktionen: Ranking, Wortstammerkennung, Hervorhebung, mehrere Sprachen integriert

Tsvector und Tsquery verstehen

-- tsvector: a processed, searchable representation of text
-- tsquery: a search query

SELECT to_tsvector('english', 'The quick brown foxes are jumping');
-- 'brown':3 'fox':4 'jump':6 'quick':2
-- Note: stemming (foxes->fox, jumping->jump) and stopword removal (the, are)

SELECT to_tsvector('english', 'The quick brown foxes')
       @@ to_tsquery('english', 'fox');
-- true - matches because 'foxes' stems to 'fox'

Einfache Volltextsuche

-- Search articles by title and content
SELECT id, title
FROM articles
WHERE to_tsvector('english', title || ' ' || content)
      @@ to_tsquery('english', 'postgresql & search');
-- & means AND, | means OR, ! means NOT

-- plainto_tsquery handles user input safely (treats as AND)
SELECT id, title
FROM articles
WHERE to_tsvector('english', title || ' ' || content)
      @@ plainto_tsquery('english', 'postgresql search tutorial');

-- websearch_to_tsquery supports Google-like syntax (quotes, OR, -)
SELECT id, title
FROM articles
WHERE to_tsvector('english', content)
      @@ websearch_to_tsquery('english', '"full text" search -elasticsearch');

Hinzufügen einer vorberechneten tsvector-Spalte mit Index

Die Berechnung von tsvector bei jeder Abfrage ist langsam. Speichern Sie es in einer Spalte mit einem GIN-Index:

-- Add a generated tsvector column (auto-updates with the data)
ALTER TABLE articles ADD COLUMN search_vector tsvector
  GENERATED ALWAYS AS (
    to_tsvector('english', coalesce(title, '') || ' ' || coalesce(content, ''))
  ) STORED;

-- Create a GIN index for fast searching
CREATE INDEX articles_search_idx ON articles USING GIN (search_vector);

-- Now searches are fast and use the index
SELECT id, title FROM articles
WHERE search_vector @@ plainto_tsquery('english', 'postgresql search');

Ranking-Ergebnisse nach Relevanz

-- ts_rank scores how well each row matches
SELECT id, title,
       ts_rank(search_vector, query) AS rank
FROM articles, plainto_tsquery('english', 'postgresql search') query
WHERE search_vector @@ query
ORDER BY rank DESC
LIMIT 20;

-- Weight title matches higher than content
ALTER TABLE articles ADD COLUMN search_vector tsvector
  GENERATED ALWAYS AS (
    setweight(to_tsvector('english', coalesce(title, '')), 'A') ||
    setweight(to_tsvector('english', coalesce(content, '')), 'B')
  ) STORED;
-- 'A' weight (title) ranks higher than 'B' weight (content)

Übereinstimmende Begriffe hervorheben

-- ts_headline returns snippets with matched terms highlighted
SELECT id, title,
       ts_headline('english', content, query,
         'StartSel=, StopSel=, MaxWords=35, MinWords=15') AS snippet
FROM articles, plainto_tsquery('english', 'postgresql') query
WHERE search_vector @@ query
ORDER BY ts_rank(search_vector, query) DESC;
-- snippet contains the relevant excerpt with  around matches

Verwenden von Node.js

app.get('/search', async (req, res) => {
  const q = req.query.q;
  if (!q) return res.json({ results: [] });

  const result = await db.query(`
    SELECT id, title,
           ts_headline('english', content, query,
             'StartSel=,StopSel=,MaxWords=35') AS snippet,
           ts_rank(search_vector, query) AS rank
    FROM articles, plainto_tsquery('english', $1) query
    WHERE search_vector @@ query
    ORDER BY rank DESC
    LIMIT 20
  `, [q]);

  res.json({ results: result.rows });
});

Hinzufügen einer unscharfen/tippfehlertoleranten Suche

-- Enable the pg_trgm extension for fuzzy matching (handles typos)
CREATE EXTENSION IF NOT EXISTS pg_trgm;

-- Trigram index for similarity search
CREATE INDEX articles_title_trgm ON articles USING GIN (title gin_trgm_ops);

-- Find titles similar to a (possibly misspelled) query
SELECT title, similarity(title, 'postgres serch') AS sim
FROM articles
WHERE title % 'postgres serch'   -- % is the similarity operator
ORDER BY sim DESC;
-- Matches 'PostgreSQL search' despite the typo

Wann Sie stattdessen Elasticsearch verwenden sollten

Die PostgreSQL-Volltextsuche bewältigt die meisten Anwendungen gut. Ziehen Sie Elasticsearch in Betracht, wenn Sie Folgendes benötigen:

  • Sehr großer Umfang (Hunderte Millionen Dokumente) mit komplexer Relevanzabstimmung
  • Erweiterte Funktionen: Facettensuche, komplexe Aggregationen, Geosuche im großen Maßstab
  • Durchsuchen Sie viele Datenquellen außerhalb Ihrer Datenbank
  • Echtzeitanalysen zu Suchdaten

Für die meisten Apps – Blogs, E-Commerce, Content-Sites, SaaS – ist die PostgreSQL-Suche einfacher, erfordert keine zusätzliche Infrastruktur und ist mehr als ausreichend.

Häufig gestellte Fragen

F: Ist die PostgreSQL-Suche gut genug oder benötige ich Elasticsearch?
A: Für die meisten Anwendungen ist die PostgreSQL-Volltextsuche mehr als ausreichend – sie verarbeitet Millionen von Dokumenten mit Ranking, Hervorhebung und Wortstammerkennung. Verwenden Sie Elasticsearch nur für sehr umfangreiche, erweiterte Facettensuche oder die Suche über viele Datenquellen hinweg. Fügen Sie die Elasticsearch-Infrastruktur nicht vorzeitig hinzu.

F: Wie gehe ich mit Tippfehlern in der Suche um?
A: Verwenden Sie die Erweiterung pg_trgm für den Trigramm-Ähnlichkeitsabgleich, die Tippfehler und Rechtschreibfehler toleriert. Kombinieren Sie es mit der Volltextsuche – verwenden Sie tsvector für die Hauptsuche und Trigram-Ähnlichkeit als Fallback oder für automatische Vervollständigung/Vorschläge.

F: Warum ist meine Volltextsuche langsam?
A: Sie berechnen to_tsvector wahrscheinlich für jede Abfrage ohne Index. Fügen Sie eine gespeicherte generierte Tsvector-Spalte mit einem GIN-Index hinzu. Dadurch wird die durchsuchbare Darstellung vorberechnet und die Suche selbst in großen Tabellen beschleunigt.

F: plainto_tsquery vs. to_tsquery vs. websearch_to_tsquery?
A: to_tsquery erfordert Operatorsyntax (&, |) – gut für programmatische Abfragen. plainto_tsquery Behandelt einfache Benutzereingaben (behandelt Wörter als UND) – sicher für Benutzersuchfelder. websearch_to_tsquery unterstützt Google-ähnliche Syntax (Anführungszeichen, OR, -) – am besten für die benutzerorientierte Suche.

F: Kann ich in mehreren Sprachen suchen?
A: Ja – PostgreSQL verfügt über Textsuchkonfigurationen für viele Sprachen (Englisch, Spanisch, Französisch usw.), die Wortstammerkennung und Stoppwörter pro Sprache verarbeiten. Geben Sie die Sprache in to_tsvector/to_tsquery an. Hinterlegen Sie eine Sprachspalte, wenn Ihr Inhalt mehrsprachig ist.

Fazit

Die integrierte Volltextsuche von PostgreSQL erfüllt die Suchanforderungen der meisten Anwendungen ohne die Komplexität einer separaten Suchmaschine. Verwenden Sie einGespeicherte generierte tsvector-Spalte mit einem GIN-Index für Leistung, ts_rank für Relevanzranking, ts_headline für Hervorhebung und pg_trgm für Tippfehlertoleranz. Gewichten Sie wichtige Felder (wie Titel) mit setweight höher und verwenden Sie plainto_tsquery oder websearch_to_tsquery für eine sichere Benutzereingabe. Reservieren Sie Elasticsearch für sehr umfangreiche oder erweiterte Facettensuche. Für Blogs, E-Commerce, Content-Sites und die meisten SaaS-Apps ist die PostgreSQL-Suche einfacher, erfordert keine zusätzliche Infrastruktur, bleibt mit Ihren Daten konsistent und bietet eine hervorragende Leistung – eine gute Standardwahl, bevor Sie zu einer dedizierten Suchinfrastruktur greifen.

MD Rafikul Islam

Written by

MD Rafikul Islam is a software developer and the editor of TechPulse. He writes about developer tooling, hardware, and the practical decisions that come up in day-to-day engineering work — which laptop to buy, which framework to commit to, why a build broke at 2am. He tests the tools he writes about and says plainly when something is not worth the money. Corrections and corrections requests are welcome at rony.yf25@gmail.com.

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇬🇧 English🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা