2011-03-04 49 views
9

我有一些关键字,比如“some-or-other”,其中的连字符在我的mysql数据库搜索中很重要。我目前使用全文功能。如何在搜索查询中允许使用连字符搜索全文搜索

有没有办法逃避连字符? 我知道一个选项是在myisam/ftdefs.h文件中注释掉#define HYPHEN_IS_DELIM,但不幸的是我的主机不允许这样做。那里有另外一个选择吗?

编辑11年3月8日 下面的代码我现在所拥有的:

$search_input = $_GET['search_input']; 
$keyword_safe = mysql_real_escape_string($search_input); 
$keyword_safe_fix = "*'\"" . $keyword_safe . "\"'*"; 


$sql = " 
    SELECT *, 
     MATCH(coln1, coln2, coln3) AGAINST('$keyword_safe_fix') AS score 
     FROM table_name 
    WHERE MATCH(coln1, coln2, coln3) AGAINST('$keyword_safe_fix') 
    ORDER BY score DESC 
"; 

回答

13

从这里http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html

一个解决方案,以找到一个词用破折号或连字符是用全文在BOOLEAN MODE中搜索,并用连字符/短划线括在双引号中。

或者从这里http://bugs.mysql.com/bug.php?id=2095

还有另一种解决方法。它最近被添加到手册中: “ 修改字符集文件:这不需要重新编译,true_word_char()宏使用”字符类型“表来区分字母和数字与其他 字符。在字符集XML 文件中的一个内容,指定“ - ”是一个然后使用给定的字符为您 FULLTEXT索引设置 “

还没有尝试过我自己“的信。”。

编辑:这是从这里http://dev.mysql.com/doc/refman/5.0/en/fulltext-boolean.html

一个短语,是双引号(““”)字符内封闭一些额外的信息只匹配字面上包含该短语的行,因为它是类型化的全。文本引擎将短语拆分为单词,并在FULLTEXT索引中执行单词搜索。在MySQL 5.0.3之前,引擎然后在找到的记录中执行子字符串搜索,因此匹配必须包含非字字符从MySQL 5.0.3开始,非字符字符不需要完全匹配:短语搜索只需要匹配包含与短语完全相同的单词并且顺序相同,例如,“测试短语”匹配“test,短语“在MySQL 5.0.3中,但不是前面。

如果短语不包含索引中的单词,则结果为空。例如,如果所有单词都是停用词或短于索引单词的最小长度,则结果为空。

+0

我实际上注意到了你提到的第一个解决方案。但是我无法复制它。你能给我一个这样的查询的例子吗? – Jay 2011-03-04 11:04:19

+2

当然,请尝试SELECT * FROM your_table_name WHERE MATCH(your_table_column_name)AGAINST(''SQL-MySQL''IN BOOLEAN MODE);在这里查看摩尔信息http://dev.mysql.com/doc/refman/5.5/en/fulltext-boolean.html – 2011-03-04 11:53:57

+0

很棒!像魅力一样工作!非常感谢你:) – Jay 2011-03-04 12:18:33

3

也许更容易使用Binary运算符。

SELECT * 
FROM your_table_name 
WHERE BINARY your_column = BINARY "Foo-Bar%AFK+LOL" 

http://dev.mysql.com/doc/refman/5.0/en/cast-functions.html#operator_binary

BINARY运营蒙上它下面的二进制字符串的字符串。这是一种简单的方法,可以逐字节而不是逐个字符地完成列比较。这会导致比较区分大小写,即使该列未被定义为BINARYBLOBBINARY也会导致尾随空格变得重要。

+1

这导致MySQL Workbench崩溃。 – mnutsch 2017-02-28 19:58:07

2

有些人会建议使用以下查询:

SELECT id 
FROM texts 
WHERE MATCH(text) AGAINST('well-known' IN BOOLEAN MODE) 
HAVING text LIKE '%well-known%'; 

但是,你需要根据使用的全文运营商许多变种。任务:实现类似+well-known +(>35-hour <39-hour) working week*的查询。太复杂了!

并且不要忘记默认长度为ft_min_word_len,因此在结果中搜索up-to-date只返回date

招数

正因为如此,我更喜欢一招,因此不需要在所有HAVING等结构:

  1. 而不是添加下面的文字到您的数据库表:

    "The Up-to-Date Sorcerer" is a well-known science fiction short story.
    副本连字符的单词没有超出注释内部文本的末尾:
    "The Up-to-Date Sorcerer" is a well-known science fiction short story.<!-- UptoDate wellknown -->

  2. 如果用户搜索up-to-date删除连字符在SQL查询:
    MATCH(text) AGAINST('uptodate ' IN BOOLEAN MODE)

通过你是用户可以找到的不是获取仅包含date(因为ft_min_word_len杀死upto)所有结果up-to-date为一个字。

当然在你之前echo的文字你应该删除<!-- ... -->评论。

优势

  • 查询是简单
  • 用户能够使用所有全文运营如常
  • 查询速度更快。
  • 如果用户搜索-well-known +science MySQL将其视为not include *well*, could include *known* and must include *science*。这不是用户所期望的。诀窍解决了从消除连字符是,太(如SQL查询-wellknown +science搜索)
0

这听起来关闭,但这种挣扎了一会儿后,我意识到,我得到我想要的结果搜索表达式。例如,如果我搜索'单词分隔'

SELECT * FROM table WHERE MATCH(column) AGAINST ('word separated'); 

根据需要返回'word-separated'的实例。这也返回其他分离和单词的实例,但将+运算符添加到每个单词可实现连字符搜索。

SELECT * FROM table WHERE MATCH(column) AGAINST ('+word +separated');