15

我有诸如“some-or-other”之类的关键字,其中连字符在通过我的 mysql 数据库进行搜索时很重要。我目前正在使用全文功能。

有没有办法逃脱连字符?我知道一种选择是#define HYPHEN_IS_DELIMmyisam/ftdefs.h文件中注释掉,但不幸的是我的主机不允许这样做。还有其他选择吗?

编辑 3-8-11 这是我现在拥有的代码:

$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
";
4

4 回答 4

18

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

查找带有破折号或连字符的单词的一种解决方案是在布尔模式下使用全文搜索,并用双引号将带有连字符/破折号的单词括起来。

或者从这里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 phrase”在 MySQL 5.0.3 中匹配“test,phrase”,但之前不匹配。

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

于 2011-03-04T10:54:49.610 回答
5

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

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*。太复杂了!

并且不要忘记默认 len ,ft_min_word_len因此搜索up-to-datedate在您的结果中返回。

诡计

因此,我更喜欢一个技巧,所以HAVING根本不需要使用 etc 的构造:

  1. 而不是将以下文本添加到数据库表中:

    《最新巫师》是一部著名的科幻短篇小说。
    将不带连字符的连字符复制到评论中文本的末尾:
    《最新巫师》是一部著名的科幻短篇小说。<!-- UptoDate wellknown -->

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

这样,您的用户可以找到up-to-date一个单词,而不是获得仅包含的所有结果date(因为ft_min_word_lenkillsupto)。

当然,echo在文本之前,您应该删除<!-- ... -->评论。

优点

  • 查询更简单
  • 用户可以像往常一样使用所有全文运算符
  • 查询速度更快。
  • 如果用户搜索-well-known +scienceMySQL,则将其视为not include *well*, could include *known* and must include *science*. 这不是用户所期望的。这个技巧也解决了这个问题(当 sql 查询搜索时-wellknown +science
于 2017-01-29T20:53:01.557 回答
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运算符将其后面的字符串转换为二进制字符串。这是强制逐字节而不是逐字符进行列比较的简单方法。即使列未定义为BINARYor ,这也会导致比较区分大小写BLOBBINARY也会导致尾随空格很重要。

于 2012-01-29T04:32:04.337 回答
0

我首选的解决方案是从搜索词和正在搜索的数据中删除连字符。我在全文表格中保留了两列 -searchreturn. search包含已删除各种字符的已清理数据,并且在我的代码也已对这些字符进行了清理之后,将用户的搜索词与之进行了比较。

然后我显示return列。

这确实意味着我的数据库中有两个数据副本,但对我来说,这种权衡是值得的。我的 FT 表只有约 500k 行,所以在我的用例中这没什么大不了的。

于 2019-06-18T17:27:22.220 回答