2012-08-23 28 views
3

如何匹配MySQL中單詞的變體,例如搜索會計應與會計師,會計師,會計師等匹配。我在共享主機上,因此無法添加任何函數到MySQL,如levenshtein。在MySQL中匹配類似/變體的單詞/後綴

我想類似於谷歌如何匹配「會計課程」和「會計課程」爲「會計課程」搜索時的東西。 Example

我的服務器語言是PHP,如果它只能在那裏實現而不是在SQL中。

當前聲明如下。

SELECT 
    pjs.title, 
    MATCH (pjs.title) AGAINST ('accountancy' IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION) AS rel1, 
    MATCH (pjs.description) AGAINST ('accountancy' IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION) AS rel2, 
    MATCH (
    pjs.benefits, 
    pjs.experienceRequirements, 
    pjs.incentives, 
    pjs.qualifications, 
    pjs.responsibilities, 
    pjs.skills 
) AGAINST ('accountancy' IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION) AS rel3 
FROM 
    pxl_jobsearch AS pjs 
ORDER BY (rel1 * 5) + (rel2 * 1.5) + (rel3) DESC; 

回答

3

MySQL並不是很擅長全文搜索,你可能會想使用其他引擎。我最喜歡的是獅身人面像(http://sphinxsearch.com/),但也有其他人。這些支持大部分都是在盒子外面進行的。

如果你有大表,並且要使用干擾,MySQL的性能可能會非常糟糕。

如果您不能使用獅身人面像,看看這個PHP腳本http://tartarus.org/~martin/PorterStemmer/php.txt

有了這個,你可以使用所產生,並在朵朵字搜索。

+0

謝謝。我很樂意使用Sphinx,之前只是簡單地介紹過它,但是仍然停留在共享主機上,所以這次沒有辦法。我沒有看到數據大小是這個網站的問題。希望如果它能起飛,我將能夠在未來改善主機。 –

+0

您可以安裝PECL軟件包:http://pecl.php.net/package/stem或者您可以檢查它是否已安裝?沒關係,你也需要雪球。 – Nin

+0

添加了一個php詞幹腳本,你應該可以在共享環境中使用它。請注意,這可能不完美。 – Nin

0

我不知道很多關於MATCH,當我要選擇與變化的專欄中,我做了以下

SELECT pjs.title 
FROM pxl_jobsearch AS pjs 
WHERE pjs.title LIKE 'account%' 

我在SQL Server中大部分工作,但做一些MySQL的。我想這也適用於MySQL。

+0

我想過使用like,但我的問題是,如果某人輸入「會計」作爲他們的搜索,我不能使用通配符來匹配「會計」(會計%)。也許我可以做出一些假設,並且總是刪除最後4個字符,以便它變成'賬戶%',但是像'信任'這樣的較短的詞將不起作用。在尋找「會計課程」時,我想要的東西類似於Google如何匹配「會計課程」和「會計課程」。 –

+0

我明白你在說什麼。這是一個很好的問題。請編輯你的問題來指定。 – Malachi

1

MySQL的SOUNDEX()函數非常接近。詳細瞭解它here

例子:

create table test(id int auto_increment, a varchar(255), primary key(id)); 
insert into test(a) values 
('accountancy'), 
('accountant'), 
('accountants'), 
('accounting'), 
('accountingc'), 
('becounting'), 
('asdf'), 
('this is a test'); 

select 
test.*, 
SOUNDEX(a), 
SOUNDEX('accountancy') 
FROM 
test 
WHERE a SOUNDS LIKE 'accountancy'; 

如果不解決這個問題,Levenshtein算法是要走的路。與您的數據庫管理員交談,他允許您創建功能。如果他這樣做,這裏的解決方案(我沒有寫的功能,歸功於匿名):

DELIMITER // 
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; 
-- max strlen=255 
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// 

再次測試數據:

create table leven(id int auto_increment, a varchar(255), primary key(id)); 
insert into leven(a) values 
('accountancy'), 
('accountant'), 
('accountants'), 
('accounting'), 
('accountingc'), 
('becounting'), 
('asdf'), 
('this is a test') 
; 


select 
leven.*, 
levenshtein(leven.a, 'accountancy') 
from 
leven 
where levenshtein(leven.a, 'accountancy') <= 3 /*or any value you like*/ 
+0

@tomdom我嘗試過SOUNDEX,但不幸的是,在這種情況下它並沒有多大幫助,但我喜歡搜索人們的姓名。 levenshtein函數聽起來很有趣,但我不能在共享主機上使用它。我想我還需要更多的規則,也許只是改變詞尾 - 後綴。 –

0

您可以使用SQL SOUNDEX(),這對您的需求非常有用:它搜索聽起來相同的單詞,而不是語法上接近的單詞。 您可以使用兩種非常相似的方法。

  • 識別常見的後綴,並與LIKE子句中%替換它們:用你的榜樣,accountancy將成爲account%
  • 編寫一個包含您需要的所有變體的「字典」,並將其用於PHP(stristr()函數):如此,accountancy將生成一個類似於WHERE value='accountancy' or value='accountant' or value='accountancies'的子句。
1

搜索引擎通過實施文本處理技術stemming來完成此操作。有很多庫爲你實現這一點,我個人有Snowball stemmer用戶,它有足夠的工作。

我對MySql的全文搜索功能不夠熟悉,但您可以嘗試將搜索算法應用於搜索條件。對於「會計課程」的例子,Snowball詞幹返回「account cours」。

+0

我已經取得了一些成功。感謝這項技術。這有助於我進一步研究。這是有趣的:http://stackoverflow.com/questions/190775/stemming-algorithm-that-produces-real-words –