Postgres टेक्स्ट सर्चिंग गाइड 2026
वे सर्च टूल्स जो पहले से आपके डेटाबेस में हैं, और हर एक कब अपना दाम निकालता है।
ज़्यादातर टीमें एक Postgres सर्च टूल इस्तेमाल करती हैं। जो टीमें तीनों जानती हैं, वे कम जटिलता के साथ बेहतर सर्च देती हैं — और उस समर्पित सर्च सर्विस से बचते हैं जिसकी उन्हें अभी ज़रूरत नहीं थी।
यह गाइड Postgres-native विकल्पों के पूरे सेट को कवर करती है: हर एक क्या करता है, यह कब सही फिट है, और इन्हें कैसे लेयर करना है।
तीन टूल्स
फुल-टेक्स्ट सर्च (tsvector / GIN इंडेक्स) शाब्दिक है। यह टेक्स्ट को लेक्सीम में टोकनाइज़ करता है, उन्हें स्टेम करता है, और क्वेरी को इंडेक्स के खिलाफ मैच करता है। “Running” और “runs” एक ही लेक्सीम में ढह जाते हैं। “dog” और “dogs” भी। रैंकिंग फंक्शन (ts_rank) उन डॉक्यूमेंट्स को इनाम देता है जहाँ क्वेरी टर्म्स बार-बार या प्रमुख रूप से दिखते हैं।
ट्राइग्राम (pg_trgm) स्ट्रिंग्स को ओवरलैपिंग 3-कैरेक्टर स्लाइस में तोड़ते हैं और यह मापते हैं कि दो स्ट्रिंग्स कितने स्लाइस शेयर करते हैं। “Dan” → " da", "dan", "an "। “Micheal” और “Michael” अपने ज़्यादातर ट्राइग्राम शेयर करते हैं, इसलिए समानता ज़्यादा है। यह pg_trgm को फज़ी नेम मैचिंग, टाइपो टॉलरेंस, और ऑटोकम्प्लीट के लिए बेहतरीन बनाता है — वह स्पेस जहाँ FTS खराब परफॉर्म करता है।
एक्ज़ैक्ट-मैच इंडेक्स (B-tree, hash) प्राइमरी कीज़, ईमेल एड्रेस, ID, SKU, और कुछ ऐसा संभालते हैं जहाँ जवाब बाइनरी है: मैच करता है या नहीं करता। ये “सर्च” जैसा फील नहीं करते, लेकिन यह बातचीत में शामिल हैं क्योंकि सबसे बुरा पैटर्न फज़ी या सेमांटिक सर्च का उपयोग उन समस्याओं के लिए करना है जिनके पास सही जवाब हैं।
चुनाव जटिलता के बारे में नहीं है। यह टूल को क्वेरी के आकार से मैच करने के बारे में है।
जब फुल-टेक्स्ट सर्च जीतता है
प्रोज़ में कीवर्ड खोजना। ब्लॉग पोस्ट, डॉक्यूमेंटेशन, प्रोडक्ट डिस्क्रिप्शन, सपोर्ट टिकट, लीगल डॉक्यूमेंट्स। FTS इस शेप के कंटेंट के लिए डिज़ाइन किया गया था: नेचरल-लैंग्वेज टेक्स्ट पर इंडेक्स्ड, रैंक्ड रिट्रीवल।
कीवर्ड-बेस्ड यूज़र क्वेरीज़। यूज़र एक सर्च टर्म टाइप करते हैं, टैग से फिल्टर करते हैं, या कीवर्ड से ब्राउज़ करते हैं। FTS उस इंटेंट को बिना किसी एम्बेडिंग इन्फ्रास्ट्रक्चर के नेटिवली हैंडल करता है।
बाहरी डिपेंडेंसी के बिना रैंक्ड रिज़ल्ट्स। FTS इंडेक्स तेज़, डिटर्मिनिस्टिक हैं, और कोई API कॉल नहीं चाहिए। रिलेवेंस सिग्नल टर्म फ्रीक्वेंसी से आता है जो फील्ड पोज़िशन से वेटेड होता है।
बूलियन फिल्टरिंग के साथ सर्च। FTS आपके मौजूदा क्वेरी लॉजिक के साथ नेचुरलली कम्पोज़ होता है:
SELECT * FROM postsWHERE search_vector @@ to_tsquery('english', 'postgres & performance') AND category = 'tutorial' AND published_at > NOW() - INTERVAL '6 months';FTS सेटअप करना
-- जेनरेटेड कॉलम इंडेक्स को ऑटोमैटिकली अप टू डेट रखता हैALTER TABLE posts ADD COLUMN search_vector tsvector GENERATED ALWAYS AS ( setweight(to_tsvector('english', coalesce(title, '')), 'A') || setweight(to_tsvector('english', coalesce(body, '')), 'B') ) STORED;
CREATE INDEX posts_search_idx ON posts USING GIN (search_vector);
-- क्वेरीSELECT title, ts_rank(search_vector, query) AS rankFROM posts, to_tsquery('english', 'postgres & performance') queryWHERE search_vector @@ queryORDER BY rank DESCLIMIT 10;setweight इम्पोर्टेंस असाइन करता है: A (टाइटल) B (बॉडी) से बड़ा है। यह ज़्यादातर कंटेंट-सर्च यूज़ केस के लिए पूरा रिलेवेंस मॉडल है।
जो FTS अच्छे से नहीं संभालता
- क्वेरी में टाइपो — “javascipt” “javascript” से मैच नहीं होगा
- परसन नेम, एड्रेस, प्रॉपर नाउन जो स्टेमिंग से अनुमानित नहीं होते
- प्रीफिक्स/ऑटोकम्प्लीट स्पेशल कॉन्फिगरेशन के बिना
- क्वेरी जहाँ यूज़र कॉन्सेप्ट बताता है बजाय नाम बताने के
जब ट्राइग्राम जीतते हैं (pg_trgm)
pg_trgm उस अजीब बीच को कवर करता है जो FTS लगातार फंबल करता है।
FTS टेक्स्ट को लेक्सीम में टोकनाइज़ करता है और स्टेम करता है। प्रोज़ के लिए यह सही है। नेम और शॉर्ट इडेंटिफायर के लिए अक्सर नहीं:
- परसन नेम (“Dan Levy” → डिक्शनरी और लैंग्वेज कॉन्फिग के आधार पर अलग-अलग स्टेम होता है)
- कंपनी नेम, एड्रेस, प्रोडक्ट टाइटल जहाँ सही स्पेलिंग मायने रखती है
- टाइपो वाली क्वेरीज़ — “Micheal Jordan”, “Amaon”, “javascipt”
- ऑटोकम्प्लीट / प्रीफिक्स सर्च
- पार्शियल स्ट्रिंग मैचिंग (“son” “Johnson”, “Anderson” से मैच करता है)
pg_trgm भाषा-अज्ञेय भी है, जो विविध भाषाई पृष्ठभूमि के नेम के लिए मायने रखता है। FTS को हर भाषा के लिए डिक्शनरी कॉन्फिगरेशन चाहिए।
फज़ी नेम सर्च
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE INDEX users_name_trgm_idx ON users USING GIN (name gin_trgm_ops);
-- "Michael Jordan" सर्च करते समय "Micheal Jordan" ढूंढता हैSELECT id, name, similarity(name, $1) AS scoreFROM usersWHERE name % $1 -- % ऑपरेटर = समानता थ्रेशोल्ड (डिफॉल्ट 0.3)ORDER BY score DESCLIMIT 10;% ऑपरेटर pg_trgm.similarity_threshold (डिफॉल्ट 0.3, रेंज 0–1) इस्तेमाल करता है। नेम सर्च के लिए, 0.3–0.4 टाइपो पकड़ता है जबकि नॉइज़ कम रखता है।
ऑटोकम्प्लीट, प्रीफिक्स, और कंटेंस सर्च
-- ऑटोकम्प्लीट के लिए प्रीफिक्स मैचिंग। ट्राइग्राम GIN इंडेक्स मदद कर सकता है,-- लेकिन प्योर लेफ्ट-एंकर्ड प्रीफिक्स के लिए B-tree पैटर्न इंडेक्स बेहतर हो सकता है।SELECT name FROM usersWHERE name ILIKE $1 || '%'ORDER BY nameLIMIT 10;
-- लंबी स्ट्रिंग्स के अंदर पार्शियल मैच के लिए word_similarity-- ("Andrew Johnson III" में से "Johnson")SELECT id, name, word_similarity($1, name) AS scoreFROM usersWHERE $1 <% nameORDER BY score DESCLIMIT 10;ट्राइग्राम GIN इंडेक्स ILIKE '%pattern%' कंटेंस क्वेरीज़ और टाइपो-टॉलरेंट मैचिंग के लिए खासतौर पर उपयोगी है — पैटर्न जो बिना ट्राइग्राम इंडेक्स के आमतौर पर फुल-टेबल स्कैन होते हैं।
कब FTS के बजाय pg_trgm पकड़ना है
| परिदृश्य | उपयोग |
|---|---|
| टाइपो के साथ परसन/कंपनी नेम सर्च | pg_trgm |
| ऑटोकम्प्लीट / प्रीफिक्स सर्च | pg_trgm (या FTS प्रीफिक्स क्वेरीज़ के साथ) |
| छोटी स्ट्रिंग्स, इडेंटिफायर, कोड | pg_trgm |
| प्रोज़ आर्टिकल्स, डॉक्स, टिकट | FTS |
| कीवर्ड के लिए लॉग मैसेज | FTS |
| मल्टीलिंगुअल नेम सर्च | pg_trgm (भाषा-अज्ञेय) |
जब एक्ज़ैक्ट-मैच SQL जीतता है
कुछ “सर्च” समस्याएँ सर्च नहीं हैं।
“ईमेल dan@example.com वाला यूज़र ढूंढो” इक्वैलिटी चेक है। “ऑर्डर ORD-12345 ढूंढो” प्राइमरी की लुकअप है। “तारीख के हिसाब से सॉर्ट किए गए tutorial कैटेगरी में पोस्ट्स लिस्ट करो” फिल्टर्ड क्वेरी है। ये B-tree या hash इंडेक्स पर हैं।
यहाँ FTS या ट्राइग्राम इस्तेमाल करने से जटिलता बढ़ती है बिना करेक्टनेस सुधारे — और एक्ज़ैक्ट इडेंटिफायर के लिए, नियर-मैच नो-मैच से बदतर है।
CREATE INDEX users_email_idx ON users (email);
-- एक्ज़ैक्ट लुकअप: तेज़ और स्पष्टSELECT id, name FROM users WHERE email = $1;व्यापक पाठ: सही जवाब वाली समस्याओं के लिए अनुमानित सर्च एक कैटेगरी एरर है। यह कुछ रिटर्न करता है — जो कॉन्फिडेंटली गलत हो सकता है।
इन टूल्स को कंबाइन करना
ये टूल्स साफ़ तरीके से कम्पोज़ होते हैं। आपको बिल्कुल एक चुनना नहीं है।
फज़ी कीवर्ड वाले सर्च बॉक्स के लिए FTS + pg_trgm:
-- टाइटल में ट्राइग्राम समानता टाइपो पकड़ता है; ts_rank बॉडी रिलेवेंस हैंडल करता हैSELECT id, title, ts_rank(search_vector, to_tsquery('simple', $1)) AS fts_rank, similarity(title, $1) AS trgm_scoreFROM postsWHERE search_vector @@ to_tsquery('simple', $1) OR title % $1ORDER BY (ts_rank(search_vector, to_tsquery('simple', $1)) + similarity(title, $1)) DESCLIMIT 10;इंटरनेशनल कंटेंट के लिए FTS + unaccent:
-- डायाक्रिटिकल मार्क्स स्ट्रिप करें ताकि "José" "Jose" से मैच करेCREATE EXTENSION IF NOT EXISTS unaccent;
CREATE TEXT SEARCH CONFIGURATION public.simple_unaccent (COPY = pg_catalog.simple);
ALTER TEXT SEARCH CONFIGURATION public.simple_unaccent ALTER MAPPING FOR hword, hword_part, word WITH unaccent, simple;
ALTER TABLE posts ADD COLUMN search_vector tsvector;
CREATE TRIGGER posts_search_vector_refreshBEFORE INSERT OR UPDATE OF title, body ON postsFOR EACH ROW EXECUTE FUNCTION tsvector_update_trigger(search_vector, 'public.simple_unaccent', title, body);इंटरनेशनल नेम सर्च के लिए unaccent + pg_trgm:
ALTER TABLE users ADD COLUMN name_search text;
CREATE FUNCTION users_name_search_refresh()RETURNS trigger LANGUAGE plpgsql AS $$BEGIN NEW.name_search := unaccent(coalesce(NEW.name, '')); RETURN NEW;END;$$;
CREATE TRIGGER users_name_search_refreshBEFORE INSERT OR UPDATE OF name ON usersFOR EACH ROW EXECUTE FUNCTION users_name_search_refresh();
CREATE INDEX users_name_search_trgm_idx ON users USING GIN (name_search gin_trgm_ops);
SELECT id, nameFROM usersWHERE name_search % unaccent($1)ORDER BY similarity(name_search, unaccent($1)) DESCLIMIT 10;ट्रिगर के उदाहरण जेनरेटेड-कॉलम या इंडेक्स एक्सप्रेशन के अंदर unaccent() इस्तेमाल करने से बचते हैं, जहाँ PostgreSQL की इम्यूटेबिलिटी रूल्स मायने रखती हैं। अगर आप अपने इम्यूटेबल फंक्शन में unaccent() रैप करते हैं, तो दस्तावेज़ करें कि आप अपग्रेड/कॉन्फिगरेशन रिस्क स्वीकार कर रहे हैं।
उल्लेखनीय एक्सटेंशन
pg_trgm ज़्यादातर Postgres डिस्ट्रिब्यूशन के साथ बंडल आता है लेकिन एक्सप्लिसिट एनेबलमेंट चाहिए। Postgres में फज़ी स्ट्रिंग मैचिंग की नींव।
unaccent इंडेक्सिंग और क्वेरी से पहले डायाक्रिटिकल मार्क्स स्ट्रिप करता है। pg_trgm और FTS दोनों के साथ यूरोपीय-लैंग्वेज कंटेंट के लिए अच्छा जोड़ी। Postgres के साथ बंडल।
pg_bigm ट्राइग्राम एप्रोच को बाइग्राम (2-कैरेक्टर स्लाइस) तक बढ़ाता है, जो CJK (चीनी, जापानी, कोरियाई) भाषाओं के लिए pg_trgm के परफॉर्मेंस में ज़बरदस्त सुधार करता है। अलग से इंस्टॉल करना होगा; बंडल नहीं।
pg_search (ParadeDB से) स्टैंडर्ड GIN / tsvector स्टैक को Tantivy-बेस्ड BM25 इंडेक्स से बदलता है। यह BM25 स्कोरिंग (अक्सर ts_rank से बेहतर), FTS क्वेरीज़ के अंदर फज़ी मिलान, फैसेटेड सर्च, और बड़ी टेबल पर ड्रामेटिकली तेज़ इंडेक्सिंग देता है। जब स्टैंडर्ड FTS रैंकिंग या परफॉर्मेंस लिमिट दिखाने लगे तो यह ड्रॉप-इन अपग्रेड पाथ है।
-- pg_search: BM25 फुल-टेक्स्ट सर्च फज़ी मैचिंग के साथCREATE INDEX posts_bm25_idx ON posts USING bm25 (id, title, body) WITH (key_field = 'id', text_fields = '{"title": {}, "body": {}}');
-- BM25 स्कोरिंग + फज़ी मैचिंग के साथ क्वेरी ("javascipt" पकड़ता है)SELECT id, title, paradedb.score(id) AS rankFROM postsWHERE posts @@@ paradedb.fuzzy_phrase(field => 'title', value => 'postgres performnce')ORDER BY rank DESCLIMIT 10;pgvector घने वेक्टर स्टोरेज और समानता सर्च जोड़ता है। यह सही टूल है जब यूज़र जो चाहते हैं उसका नाम बताने के बजाय ब्याख्या करते हैं — सेमांटिक सर्च, RAG, रिलेटेड-कंटेंट रिकमेंडेशन, मल्टीलिंगुअल क्वेरी। Semantic Vector Search and Hybrid Strategies में गहराई से कवर किया गया है।
डिसीज़न टेबल
| जो आप सर्च कर रहे हैं | अनुशंसित |
|---|---|
| प्रोज़ आर्टिकल्स, डॉक्स, टिकट | FTS |
| टाइपो के साथ परसन/कंपनी नेम | pg_trgm |
| ऑटोकम्प्लीट, प्रीफिक्स सर्च | pg_trgm |
| छोटे कोड, इडेंटिफायर | pg_trgm |
| कीवर्ड के लिए लॉग मैसेज | FTS |
| इंटरनेशनल नेम | pg_trgm + unaccent |
| बड़ा कंटेंट, बेहतर रैंकिंग | pg_search (ParadeDB BM25) |
| प्राइमरी कीज़, एक्ज़ैक्ट ईमेल, ID | B-tree इंडेक्स |
| तारीख, रेंज, सॉर्टेड लिस्ट | B-tree इंडेक्स |
| परमिशन, कैटेगरी, फिल्टर | रेगुलर WHERE क्लॉज़ |
| सवाल, पैराफ्रेज़, कॉन्सेप्ट | pgvector (अगला आर्टिकल देखें) |
संदेह में: स्पेलिंग वेरिएशन के साथ छोटी स्ट्रिंग्स → ट्राइग्राम। कीवर्ड क्वेरी के लिए लंबा प्रोज़ → FTS। स्ट्रक्चर्ड इडेंटिफायर → रेगुलर इंडेक्स। कॉन्सेप्टुअल या नेचरल-लैंग्वेज क्वेरी → pgvector।
हाइब्रिड सर्च: दो सिग्नल, एक रैंक
जब "withRetry timeout errors" जैसी क्वेरी सर्च बॉक्स में आती है, इसमें दो तरह का इंटेंट होता है: एक्ज़ैक्ट सिंबल नेम जो यूज़र जानता है (withRetry) और कॉन्सेप्टुअल डिस्क्रिप्शन (timeout errors)। कोई एक प्रिमिटिव दोनों को कवर नहीं करता। FTS और वेक्टर सर्च को पैरलल में रन करना — फिर Reciprocal Rank Fusion से उनकी रैंक्ड लिस्ट मर्ज करना — करता है।
RRF हर रिज़ल्ट को 1 / (60 + rank) स्कोर करता है हर लिस्ट में और लिस्ट्स में सब करता है। कॉन्स्टेंट 60 टॉप रैंक के फायदे को डैम्प करता है, ताकि दोनों लिस्ट में दूसरे नंबर पर रहने वाला रिज़ल्ट एक लिस्ट में जीतने वाले और दूसरी में पूरी तरह मिस करने वाले को हरा सके। ज़रूरी बात: RRF कभी भी मेथड्स में रॉ स्कोर औसत नहीं करता — FTS रैंक और कोसाइन दूरी अलग करेंसी हैं और अरिथमेटिकली कंबाइन नहीं किए जा सकते।
-- हाइब्रिड सर्च: RRF से मर्ज किया गया FTS + pgvectorWITH fts AS ( SELECT id, ts_rank(search_vector, query) AS score, ROW_NUMBER() OVER (ORDER BY ts_rank(search_vector, query) DESC) AS rank FROM docs, to_tsquery('english', 'withRetry & timeout') query WHERE search_vector @@ query LIMIT 60),vec AS ( SELECT id, ROW_NUMBER() OVER (ORDER BY embedding <=> $embedding) AS rank FROM docs ORDER BY embedding <=> $embedding LIMIT 60)SELECT COALESCE(fts.id, vec.id) AS id, (COALESCE(1.0 / (60 + fts.rank), 0) + COALESCE(1.0 / (60 + vec.rank), 0)) AS rrf_scoreFROM fts FULL JOIN vec ON fts.id = vec.idORDER BY rrf_score DESCLIMIT 10;60-डॉक्यूमेंट कैंडिडेट पुल पर ब्रांच (LIMIT 60) एक कॉमन स्टार्टिंग पॉइंट है। रिकॉल कम हो तो चौड़ा करें; स्पीड के लिए संकुचित करें।
आगे क्या है
Postgres टेक्स्ट सर्च बहुत ज़मीन कवर करता है, लेकिन इसकी एक सीलिंग है। जब यूज़र जो चाहते हैं उसका नाम बताने के बजाय ब्याख्या करते हैं — “फ्लाइट में सोने में मदद करने वाला कुछ,” “डिबगिंग कॉन्फिडेंस के बारे में आर्टिकल्स एक नए इंजीनियर के रूप में” — शाब्दिक और ट्राइग्राम सर्च दोनों फेल होते हैं।
यह वेक्टर एम्बेडिंग, सेमांटिक सर्च, और हाइब्रिड आर्किटेक्चर का टेरिटरी है। Semantic Vector Search and Hybrid Strategies में कवर किया गया है।