2010-04-28 15 views
14

मेरे पास ~ 300.000 पंक्ति तालिका है; जिसमें तकनीकी शर्तें शामिल हैं; PHP और MySQL + FULLTEXT अनुक्रमणिका का उपयोग करके पूछताछ की गई। लेकिन जब मैं गलत टाइप अवधि की खोज करता हूं; उदाहरण के लिए "हाइपरपेक्स्ट"; स्वाभाविक रूप से कोई परिणाम नहीं दे रहा है।"क्या आपका मतलब है" एक शब्दकोश डेटाबेस पर सुविधा

मुझे छोटी लेखन त्रुटियों को "compansate" और डेटाबेस से निकटतम रिकॉर्ड प्राप्त करने की आवश्यकता है। मैं इस तरह के feaure कैसे पूरा कर सकते हैं? मुझे पता है (वास्तव में, आज सीखा है) लेवेनशेटिन दूरी, साउंडएक्स और मेटाफोन एल्गोरिदम के बारे में, लेकिन वर्तमान में डेटाबेस के खिलाफ पूछताछ के लिए इसे लागू करने के लिए ठोस विचार नहीं है।

सर्वश्रेष्ठ संबंध। (मेरे गरीब अंग्रेजी के बारे में क्षमा करें, मैं अपना सर्वश्रेष्ठ करने के लिए कोशिश कर रहा हूँ)

उत्तर

11

के लिए यह लेख देखें आप हो सकता है implement Levenshtein distance in a MySQL stored function कैसे।

भावी पीढ़ी के लिए, लेखक का सुझाव यह करने के लिए है:

CREATE FUNCTION LEVENSHTEIN (s1 VARCHAR(255), s2 VARCHAR(255)) 
    RETURNS INT 
    DETERMINISTIC 
     BEGIN 
     DECLARE s1_len, s2_len, i, j, c, c_temp, cost INT; 
     DECLARE s1_char CHAR; 
     DECLARE cv0, cv1 VARBINARY(256); 
     SET s1_len = CHAR_LENGTH(s1), s2_len = CHAR_LENGTH(s2), cv1 = 0x00, j = 1, i = 1, c = 0; 
     IF s1 = s2 THEN 
      RETURN 0; 
     ELSEIF s1_len = 0 THEN 
      RETURN s2_len; 
     ELSEIF s2_len = 0 THEN 
      RETURN s1_len; 
     ELSE 
      WHILE j <= s2_len DO 
      SET cv1 = CONCAT(cv1, UNHEX(HEX(j))), j = j + 1; 
      END WHILE; 
      WHILE i <= s1_len DO 
      SET s1_char = SUBSTRING(s1, i, 1), c = i, cv0 = UNHEX(HEX(i)), j = 1; 
      WHILE j <= s2_len DO 
       SET c = c + 1; 
       IF s1_char = SUBSTRING(s2, j, 1) THEN SET cost = 0; ELSE SET cost = 1; END IF; 
       SET c_temp = CONV(HEX(SUBSTRING(cv1, j, 1)), 16, 10) + cost; 
       IF c > c_temp THEN SET c = c_temp; END IF; 
       SET c_temp = CONV(HEX(SUBSTRING(cv1, j+1, 1)), 16, 10) + 1; 
       IF c > c_temp THEN SET c = c_temp; END IF; 
       SET cv0 = CONCAT(cv0, UNHEX(HEX(c))), j = j + 1; 
      END WHILE; 
      SET cv1 = cv0, i = i + 1; 
      END WHILE; 
     END IF; 
     RETURN c; 
     END 

वह भी एक LEVENSHTEIN_RATIO सहायक विधि है जो अलग अलग/कुल पात्रों के अनुपात है, बजाय एक सीधे संपादित दूरी का मूल्यांकन करेंगे आपूर्ति करती है। उदाहरण के लिए, यदि यह 60% है, तो स्रोत शब्द में वर्णों के तीन-पांचवें गंतव्य शब्द से अलग हैं।

CREATE FUNCTION LEVENSHTEIN_RATIO (s1 VARCHAR(255), s2 VARCHAR(255)) 
    RETURNS INT 
    DETERMINISTIC 
     BEGIN 
     DECLARE s1_len, s2_len, max_len INT; 
     SET s1_len = LENGTH(s1), s2_len = LENGTH(s2); 
     IF s1_len > s2_len THEN SET max_len = s1_len; ELSE SET max_len = s2_len; END IF; 
     RETURN ROUND((1 - LEVENSHTEIN(s1, s2)/max_len) * 100); 
     END 
+0

पोस्टरिटी के लिए भी, यह जेसन रस्ट द्वारा कोड है जो आर्नोल्ड फ़्रिबल द्वारा कोड पर आधारित है, जो बदले में आंशिक रूप से जोसेफ गामा से काम पर आधारित था। – webbiedave

+0

डी ओह। किसी तरह मैंने सोचा कि मैं लेखक का उल्लेख करता हूं, लेकिन जाहिर है मैंने नहीं किया। अंतराल भरने के लिए धन्यवाद, @webbiedave। –

+1

यूडीएफ के लिए धन्यवाद, यह बहुत उपयोगी है। लेकिन अगर मैं एक क्वेरी चलाता हूं जैसे "चयन * तालिका से जहां LEVENSHTEIN ('कीवर्ड', फ़ील्ड) <3 (या तो)" ~ 300k पंक्ति तालिका पर है, तो यह (स्पष्ट रूप से) पूर्ण होने में आयु लेता है। मैंने पंक्तियों की खोज को कम करने की कोशिश की (CHAR_LENGTH ('कीवर्ड') - 1 और CHAR_LENGTH ('कीवर्ड') + 1 के बीच WHERE CHAR_LENGTH ('फ़ील्ड') का उपयोग करके) लेकिन यह 35 सेकंड में परिणाम देता है :) क्या आप (या अन्य) इस सवाल को तेज करने के लिए एक विचार है? – Hazar

1

http://dev.mysql.com/doc/refman/5.0/en/udf-compiling.html

की टिप्पणी से अब मैं mysql यूडीएफ रिपोजिटरी से पैकेज को डाउनलोड http://empyrean.lib.ndsu.nodak.edu/~nem/mysql/

wget http://empyrean.lib.ndsu.nodak.edu/~nem/mysql/udf/dludf.cgi?ckey=28 

ll 

tar -xzvf dludf.cgi\?ckey\=28 

gcc -shared -o libmysqllevenshtein.so mysqllevenshtein.cc -I/usr/include/mysql/ 

mv libmysqllevenshtein.so /usr/lib 

mysql -uroot -pPASS 

mysql> use DATABASE 

mysql> CREATE FUNCTION levenshtein RETURNS INT SONAME 'libmysqllevenshtein.so'; 

mysql> select levenshtein(w1.word,w2.word) as dist from word w1, word w2 where ETC........... order by dist asc limit 0,10; 
-1

क्यों नहीं में शब्द के भंडारण के लिए एक मेज स्तंभ जोड़ने इसका वैकल्पिक (उदाहरण के लिए, साउंडएक्स) रूप? इस तरह, यदि आपका पहला चयन सटीक मिलान नहीं मिलता है, तो आप वैकल्पिक रूपों से मेल खाने के लिए दूसरी खोज कर सकते हैं।

चाल प्रत्येक शब्द को एन्कोड करना है ताकि गलत वर्तनी विविधताएं एक ही वैकल्पिक रूप में परिवर्तित हो जाएं।

0

मेरा सुझाव है कि आप क्वेरी इनपुट पर generate typo विविधताएं हैं।

यानी hyperpext> {hyperpeext, hipertext, ...} आदि

इनमें से एक (प्रयोग गलत वर्तनी के लिए विशेष रूप से)

जिस तरह से आप की पहचान सबसे अच्छा मिलान है सही वर्तनी होने के लिए बाध्य किया जाता है एक इंडेक्स पर प्रत्येक के लिए एक लुकअप करने के लिए जो आपको शब्द की दस्तावेज़ आवृत्ति बताता है। (समझ में आता है?)

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