2010-03-25 11 views
11

यहां एक प्रश्न के बाद पोस्ट किया गया है कि मैं अपने SQL खोज विधियों में से एक पर गति कैसे बढ़ा सकता हूं, मुझे सलाह दी गई थी कि पूर्ण टेक्स्ट खोज का उपयोग करने के लिए मेरी तालिका अपडेट करें। तेजी से खोज करने के लिए जिस्ट इंडेक्स का उपयोग करके मैंने यह किया है। कुछ "सादा" प्रश्नों पर मैंने एक उल्लेखनीय वृद्धि देखी है जिसे मैं बहुत खुश हूं।PostgreSQL: पूर्ण पाठ खोज - आंशिक शब्दों को कैसे खोजें?

हालांकि, मुझे आंशिक शब्दों की खोज में कठिनाई हो रही है। उदाहरण के लिए मेरे पास कई रिकॉर्ड हैं जिनमें स्क्वायर शब्द (454) है और मेरे पास कई रिकॉर्ड हैं जिनमें गिलहरी (173) शामिल हैं। अब अगर मैं स्क्वायर की खोज करता हूं तो यह केवल 454 रिकॉर्ड लौटाता है लेकिन मैं यह भी चाहता हूं कि यह गिलहरी रिकॉर्ड भी वापस कर दे।

मेरे क्वेरी इस

SELECT title 
FROM movies 
WHERE vectors @@ to_tsoquery('squire'); 

मैंने सोचा कि मैं to_tsquery('squire%') कर सकता है की तरह लग रहा है, लेकिन वह काम नहीं करता।
आंशिक मिलान खोजने के लिए मैं इसे कैसे प्राप्त करूं?

इसके अलावा, मेरे डेटाबेस में मेरे पास रिकॉर्ड हैं जो फिल्में और अन्य टीवी शो हैं। इन्हें नाम से अलग किया जाता है, इसलिए "मुनस्टर" एक टीवी शो है, जबकि मुन्स्टर शो की फिल्म है। मैं जो करने में सक्षम होना चाहता हूं वह सिर्फ टीवी शो और सिर्फ फिल्मों की तलाश है। इस पर कोई विचार है कि मैं इसे कैसे प्राप्त कर सकता हूं?

सादर Anthoni

+0

यदि आपके पास सर्चकी 'स्क्वायर' है लेकिन परिणाम' गिलहरी 'प्राप्त करना चाहते हैं, तो आपको अतिरिक्त बाधाएं निर्दिष्ट करनी पड़ सकती हैं। क्योंकि अन्यथा कोई तर्क दे सकता है कि उनके पास खोज कुंजी 'माँ' थी लेकिन परिणाम 'खरगोश' चाहता था। तो शायद आप अपनी खोज कुंजी को टुकड़ा करना चाहें और 'squire' को 's' में बदलना चाहें वर्ग | एसएल | स्की | स्क्वायर | squire' ... यह या fancier एल्गोरिदम आपको 'गिलहरी' मिल जाएगा।मुझे लगता है कि @ जोशुआ बर्न्स के जवाब में मेरे मुकाबले एक सामान्य जेनेरिक समाधान है, यदि आप सामान्य होना चाहते हैं। –

उत्तर

4

भी LIKE का उपयोग कर आप squire% से 'गिलहरी' प्राप्त करने में सक्षम है क्योंकि 'गिलहरी' दो 'आर के नहीं होगा। स्क्वायर हो और गिलहरी आप निम्न क्वेरी चला सकते हैं करने के लिए:

SELECT title FROM movies WHERE vectors @@ to_tsquery('squire|squirrel'); 

फिल्मों और टीवी के बीच अंतर करने से पता चलता है कि आप अपने डेटाबेस के लिए एक स्तंभ जोड़ना चाहिए। हालांकि, इस बिल्ली को त्वचा के कई तरीके हैं। आप 'स्क्वायर' और 'गिलहरी' से मेल खाने वाली फिल्मों को पहली बार ढूंढने के लिए पोस्टग्रेस को मजबूर करने के लिए उप-क्वेरी का उपयोग कर सकते हैं और उसके बाद उस सबसेट को '' 'से शुरू होने वाले शीर्षक ढूंढने के लिए खोज सकते हैं। LIKE '"%...' खोजों में उपयोग के लिए इंडेक्स बनाना संभव है ।

SELECT title 
FROM (
    SELECT * 
    FROM movies 
    WHERE vectors @@ to_tsquery('squire|squirrel') 
) t 
WHERE title ILIKE '"%'; 

या

SELECT title 
FROM movies 
WHERE vectors @@ to_tsquery('squire|squirrel') 
    AND title ILIKE '"%'; 
0

एक बात है कि काम कर सकते हैं शब्द को तोड़ने है: गंदगी के आसपास उन लोगों के साथ है जो खोजने के लिए सबसे तेजी से -

अन्य अनुक्रमण संभावनाओं के बिना आप भी इन चला सकते हैं आप छोटे पी में खोज रहे हैं कला। तो आप उन चीजों की तलाश कर सकते हैं जिनमें स्की या क्वियर या स्क्वायर या आदि हैं ... मुझे यकीन नहीं है कि यह कितना कुशल होगा, लेकिन इससे मदद मिल सकती है।

जब आप फिल्म या फिल्म की खोज करते हैं तो आप टेक्स्ट को एकल कोट में रखने का प्रयास कर सकते हैं। तो यह या तो 'शो' या 'शो' होगा। मुझे लगता है कि यह भी काम कर सकता है।

27

प्रयास करें,

SELECT title FROM movies WHERE to_tsvector(title) @@ to_tsquery('squire:*') 

यह PostgreSQL 8 पर काम करता है।4

+2

आपने उपसर्ग मिलान के साथ एक लेक्समे निर्दिष्ट किया है, लेकिन यह समस्या का समाधान नहीं करेगा: यह अभी भी 'आर' गायब है। आपको शायद यह जवाब हटा देना चाहिए। –

+2

@ रिचर्ड माइकल मैं असहमत हूं क्योंकि यह विधि काम करती है। ओपी दो शब्दों को पाने की कोशिश कर रहा है जो समान नहीं हैं। 'squire' ** ** नहीं है 'गिलहरी' शब्द का आंशिक। उन्होंने आंशिक मैच के लिए कहा और यह जवाब यह करता है। इसे ऊपर उठाया जाना चाहिए। –

+0

इसके लिए धन्यवाद, मेरे पास उपयोग के मामले में मदद मिली है। +1 –

25

Anthoni,

आप केवल ASCII एन्कोडिंग का उपयोग करने की योजना मान लिया जाये कि (, मुझे पता है हूँ मुश्किल हो सकता है), एक बहुत व्यवहार्य विकल्प trigram (pg_trgm) मॉड्यूल हो सकता है: http://www.postgresql.org/docs/9.0/interactive/pgtrgm.html

trigram अंतर्निहित इंडेक्सिंग विधियों का उपयोग करता है जैसे कि जिस्ट और जिन। आपके सूचकांक को परिभाषित करते समय आपको केवल एक ही संशोधन करना है, gist_trgm_ops या gin_trgm_ops का ऑपरेटर क्लास निर्दिष्ट करें।

योगदान मॉड्यूल पहले से स्थापित नहीं कर रहे हैं, उबंटू में यह रूप में आसान और खोल से निम्न आदेश चलाकर है:

# sudo apt-get install postgresql-contrib 

योगदान मॉड्यूल के बाद उपलब्ध कराया जाता है, तो आप में pg_trgm विस्तार स्थापित करना होगा प्रश्न में डेटाबेस। आप डेटाबेस पर निम्न PostgreSQL क्वेरी को निष्पादित कर ऐसा कर आप में मॉड्यूल स्थापित करने के लिए चाहते हैं: pg_trgm विस्तार

CREATE EXTENSION pg_trgm; 

के बाद स्थापित किया गया है, हम कुछ मस्ती करने के लिए तैयार हैं!

-- Create a test table. 
CREATE TABLE test (my_column text) 
-- Create a Trigram index. 
CREATE INDEX test_my_colun_trgm_idx ON test USING gist (my_column gist_trgm_ops); 
-- Add a couple records 
INSERT INTO test (my_Column) VALUES ('First Entry'), ('Second Entry'), ('Third Entry') 
-- Query using our new index -- 
SELECT my_column, similarity(my_column, 'Frist Entry') AS similarity FROM test WHERE my_column % 'Frist Entry' ORDER BY similarity DESC 
+2

यह स्वीकार्य उत्तर क्यों नहीं है? अब तक का सबसे अच्छा है :) – jperelli

+0

आपके उदाहरण में समानता सही शब्द का उपयोग करती है, न कि आपके कहां खंड में उपयोग की जाने वाली गलत वर्तनी शब्द। समानता का चयन करें ('फ्रिस्ट एंट्री', 'फर्स्ट एंट्री') => 0.5 –

+0

अच्छा बिंदु, मेरे अंत में टाइपो। संकल्प लिया। सिर के लिए धन्यवाद :) –

4

@ एलेक्सेंडर-मेरा समाधान बहुत अच्छा काम करता है!

नोट: यह भी सुनिश्चित करें कि रिक्त स्थान + पर परिवर्तित करें। उदाहरण के लिए, यदि आप squire knight खोज रहे हैं।

SELECT title FROM movies WHERE to_tsvector(title) @@ to_tsquery('squire+knight:*') 
+0

'+' का उपयोग करना PosgreSQL 9.4.1 पर मेरे लिए काम नहीं करता है। अगर मैं 'एंड' का उपयोग करता हूं, तो एक आकर्षण की तरह काम करता है। – facundofarias

0

यह करने के लिए व्यापक समाधान एक उपनाम तालिका कि वैकल्पिक मैचों (Query Rewriting देखें) के लिए काम करता है सेटअप करने के लिए पीजी की ts_rewrite समारोह का प्रयोग है। यह जबकि ऊपर तुम्हारा भी आदि उस लिंक पर tree rat के लिए खोज और squirrel के परिणाम प्राप्त होने,

पूर्ण विवरण और स्पष्टीकरण की तरह पूरी तरह से अलग मामलों से निपटने तरह के मामलों को शामिल किया गया है, लेकिन यह का सार है कि आप सेटअप के साथ एक उपनाम तालिका कर सकते है 2 ts_query कॉलम और अपनी खोज के साथ में है कि तालिका के एक प्रश्न गुजरती हैं, जैसे इतना:

WHERE vectors @@ ts_rewrite(to_tsquery('supernovae & crab'), 'SELECT * FROM aliases') 

यह समान है:

CREATE TABLE aliases (t tsquery primary key, s tsquery); 
INSERT INTO aliases VALUES(to_tsquery('supernovae'), to_tsquery('supernovae|sn')); 

SELECT ts_rewrite(to_tsquery('supernovae & crab'), 'SELECT * FROM aliases'); 

एक अंतिम प्रश्न है कि लग रहा है और अधिक की तरह में परिणामी पीजी के भीतर थिसॉरस सेटअप के लिए, लेकिन हर बार जब आप कुछ जोड़ते हैं तो पूर्ण रीइंडेक्स की आवश्यकता के बिना काम करता है। जैसे-जैसे आप थोड़ी-थोड़ी वर्तनी भिन्नताओं और "जब मैं इसकी खोज करता हूं, तो मुझे इस तरह के परिणाम की उम्मीद होती है" के मामले में आते हैं, बस उन्हें जल्दी से तालिका में जोड़ना बहुत आसान होता है। आप उस तालिका में और कॉलम जोड़ सकते हैं, साथ ही साथ ts_rewrite पर आधारित क्वेरी 2 अपेक्षित to_tsquery कॉलम लौटाती है।

जब आप उस दस्तावेज़ में खोदते हैं तो आपको प्रदर्शन ट्यूनिंग के लिए भी सुझाए गए उदाहरण दिखाई देंगे। शुद्ध गति के लिए ट्रिग्राम का उपयोग करने और वेक्टर/क्वेरी/मजबूती के लिए पुनः लिखने के बीच संतुलन है।

संबंधित मुद्दे