1

我有以下查询

SELECT * 
FROM  `articles` 
WHERE (
        (
        UCASE(  `title` ) LIKE UCASE(  '% Fishoil %' ) 
        AND UCASE(  `title` ) LIKE UCASE(  '% for %' ) 
        AND UCASE(  `title` ) LIKE UCASE(  '% more %' ) 
        AND UCASE(  `title` ) LIKE UCASE(  '% musclemass %' )
        )
    OR (
        UCASE(  `text` ) LIKE UCASE(  '% Fishoil %' ) 
        AND UCASE(  `text` ) LIKE UCASE(  '% for %' ) 
        AND UCASE(  `text` ) LIKE UCASE(  '% more %' ) 
        AND UCASE(  `text` ) LIKE UCASE(  '% musclemass %' )
        )
    OR (
        UCASE(  `source` ) LIKE UCASE(  '% Fishoil %' ) 
        AND UCASE(  `source` ) LIKE UCASE(  '% for %' ) 
        AND UCASE(  `source` ) LIKE UCASE(  '% more %' ) 
        AND UCASE(  `source` ) LIKE UCASE(  '% musclemass %' )
        )
    OR (
        UCASE(  `unique` ) LIKE UCASE(  '% Fishoil %' ) 
        AND UCASE(  `unique` ) LIKE UCASE(  '% for %' ) 
        AND UCASE(  `unique` ) LIKE UCASE(  '% more %' ) 
        AND UCASE(  `unique` ) LIKE UCASE(  '% musclemass %' )
        )
    )
ORDER BY  `year` DESC

我想做的是改变

UCASE(  `tile` ) LIKE UCASE(  '% Fishoil %' )

进入

 UCASE(  `title` ) LIKE UCASE(  '%Fishoil %' ) 
OR 
    UCASE(  `title` ) LIKE UCASE(  '%Fishoil,%' ) 
OR 
    UCASE(  `title` ) LIKE UCASE(  '%Fishoil.%' ) 
OR 
    UCASE(  `title` ) LIKE UCASE(  '%Fishoil:%' ) 
OR 
    UCASE(  `title` ) LIKE UCASE(  '%Fishoil;%' ) 
OR 
    UCASE(  `title` ) LIKE UCASE(  '%Fishoil\'%' ) 
OR 
    UCASE(  `title` ) LIKE UCASE(  '%Fishoil"%' ) 
OR 
    UCASE(  `title` ) LIKE UCASE(  '%Fishoil!%' ) 
OR 
    UCASE(  `title` ) LIKE UCASE(  '%Fishoil?%' )

但在我看来,这似乎使查询变得异常复杂,因为它必须进行多次匹配。是否有一种正则表达式匹配可以一次性匹配“搜索词+特殊字符”?

如果是这样,与它匹配的最佳方法是什么?

这是生成关键字搜索字符串的 php 代码

$specialchars = array(' ',',','.',':',';',mysql_real_escape_string("'"),'"','!','?');
foreach($seek as $searchword)
    {
    foreach($specialchars as $char)
        {
        $seeker[] = "LIKE UCASE(  '%$searchword".$char."%' )";
        }
    $temp = implode(" OR ",$seeker);
    echo $temp;
    }
4

3 回答 3

2

我建议你使用正则表达式,因为它们比通配符LIKE语法强大得多。通过使用正则表达式,您可以将整组条件放入一个REGEXP调用(每列)中。

于 2012-09-19T11:34:04.907 回答
1

不要为每个字符添加 or 子句,而是使用下划线 ( _)。这就像一个通配符,除了一件事:它是单个字符的占位符:

SELECT * FROM foo WHERE bar LIKE 'visolie_';

匹配 visolie!、visolie:、visolie? 和 - 因为 like 也是不区分大小写的 ViSOliE!。

编辑:

出于所有意图和目的:有许多优秀的搜索引擎是由非常聪明的人编写的,并且仍在由一群有能力的程序员进一步开发。尝试创建自己的 SE 可能是一个很好的练习,但当它真正归结为它时,只需使用CSE
他们已经为您完成了艰苦的工作,作为开发人员意味着以一种聪明的方式偷懒。开源软件以及网络的全部意义在于避免不断重复发明轮子的必要性。

如果您绝对想构建自己的 SE,PHP&MySQL 是经过验证的技术,但可能不是完成这项工作的最佳工具。尝试寻找更快的数据库(NoSQL?)替代品(MongoDB 会浮现在脑海中,只要您不经常更新数据,它的速度非常快。再次:选择一个意味着失去另一个,您的数据并不安全存储...)。
PHP 相当快,但与 C++ 相比,它占用了大量资源。我不确定我是否做对了,但我准备赌一大笔钱,说 SE 就像谷歌,雅虎!甚至糟糕的旧 Bing 在某处也有相当庞大的 C(++) 代码库。迄今为止,没有任何脚本语言可以超越它,(而且 IMO 永远不会有脚本语言可以)

于 2012-09-19T11:35:39.287 回答
0

FULLTEXT可能值得一看

你可以做这样的事情;

SELECT *, MATCH(title,text,source,unique) AGAINST('fishoil for more musclemass') AS `score` FROM `articles` WHERE MATCH(title,text,source,unique) AGAINST('fishoil for more musclemass') ORDER BY `score` DESC, `year` DESC

whcih 将首先返回最相关的结果。

您也必须更改您的 SQL 表;

ALTER TABLE articles ADD FULLTEXT(title,text,source,unique);

希望这可以帮助

于 2012-09-19T11:43:29.743 回答