我有像“some-or-other”这样的关键字,其中连字符在搜索我的mysql数据库时很重要。我目前正在使用全文功能。
有没有办法逃脱连字符?
我知道一个选项是在 myisam / ftdefs.h 文件中注释掉#define HYPHEN_IS_DELIM
,但不幸的是我的主持人不允许这样做。还有其他选择吗?
编辑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
";
答案 0 :(得分:16)
从这里http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html
找到带有破折号或连字符的单词的一种解决方案是在BOOLEAN MODE中使用FULL TEXT SEARCH,并用双引号将连字符/破折号括起来。
或者从这里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开始,非单词字符不必是完全匹配:短语搜索只需要匹配包含与短语完全相同的单词并且顺序相同。例如,“测试短语”与MySQL 5.0.3中的“test,phrase”匹配,但之前不匹配。
如果短语不包含索引中的单词,则结果为空。例如,如果所有单词都是停用词或短于索引单词的最小长度,则结果为空。
答案 1 :(得分: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
运算符将其后面的字符串转换为二进制字符串。这是一种简单的方法,可以逐个字节而不是逐个字符地强制进行列比较。这会导致比较区分大小写,即使该列未定义为BINARY
或BLOB
。 BINARY
也会导致尾随空格显着。
答案 2 :(得分: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
的默认len,因此搜索up-to-date
只会在结果中返回date
。
<强>招强>
因为我更喜欢一个技巧,所以根本不需要使用HAVING
等构造:
而不是将以下文本添加到数据库表中:
"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 -->
如果用户搜索up-to-date
,请删除sql查询中的连字符:
MATCH(text) AGAINST('uptodate ' IN BOOLEAN MODE)
用户可以将up-to-date
作为一个单词找到,而不是获取仅包含date
的所有结果(因为ft_min_word_len
会导致up
和{{1} })。
当然,在您to
文本之前,您应删除echo
条评论。
<强>优点强>
<!-- ... -->
,则将其视为-well-known +science
。这不是用户期望的。这个技巧也解决了这个问题(因为sql查询搜索not include *well*, could include *known* and must include *science*
)答案 3 :(得分:0)
这可能听起来很糟糕,但经过一段时间的努力,我意识到我通过从搜索表达式中删除连字符得到了我想要的结果。例如,如果我搜索单词分隔的&#39;
s3.Bucket('bucketname').upload_file('/local/file/here.txt','folder/sub/path/to/s3key')
返回&#39;单词分隔&#39;如所须。这也会返回其他分隔和单词的实例,但是为每个单词添加SELECT * FROM table WHERE MATCH(column) AGAINST ('word separated');
运算符可以实现连字符搜索。
+
答案 4 :(得分:0)
我对此的首选解决方案是从搜索词和正在搜索的数据中删除连字符。我在全文表中保留了两列-search
和return
。 search
包含已删除各种字符的已清理数据,并且在我的代码也已对其进行清理之后,将这些数据与用户的搜索字词进行了比较。
然后显示return
列。
这确实意味着我在数据库中有两个数据副本,但是对我而言,这种折衷是值得的。我的FT表只有约50万行,因此在我的用例中没什么大不了的。