Perl MySQL 全文搜索

Perl MySQL Fulltext Search

我是这个网站的新手。

我有以下代码来搜索具有全文索引的三列。 (searchdatabase.title, searchdatabase.keywords, searchdatabase.description)

$SQL_QUERY=<<__CURSOR_1__;
select distinct url, keywords, description, title from searchdatabase 
where match ( searchdatabase.title, searchdatabase.keywords, 
searchdatabase.description ) against ('$datasent' IN BOOLEAN MODE)
order by authority_rank desc, rank desc limit 10 offset $page;
__CURSOR_1__


$dbh = DBI -> connect ($dns, $username, $password) 
or &Error("Can not connect to database.");

$cursor = $dbh->prepare( "$SQL_QUERY" );
$cursor->execute;

由于我对 Perl 全文搜索和 SQL 的了解有限,我在上面的代码之前有以下代码来做一些 SQL 注入预防和空格“+”以便搜索。

$datasent =~ s/ / +/g;
$datasent =~ s/ / +/g;
$datasent =~ s/\n//g;
$datasent =~ s/<//g;
$datasent =~ s/\x00//g;
$datasent =~ s/\r//g;
$datasent =~ s/\x1a//g;
$datasent =~ s/\;//g; 
$datasent =~ s/\*//g; 
$datasent =~ s/\'//g; 
$datasent =~ s/\"//g; 

这样做正确吗? 我觉得把空格变成“+”有点不对...

DBI's placeholders 是去这里的路。它将为您处理转义内容。

my $sql = <<'CURSOR_1';
select distinct url, keywords, description, title
from searchdatabase where
match ( searchdatabase.title, searchdatabase.keywords, searchdatabase.description )
against (? IN BOOLEAN MODE)
order by authority_rank desc, rank desc limit 10 offset $page;
CURSOR_1

您基本上将 ? 放入查询中。调用的时候把参数传入execute.

my $sth = $dbh->prepare( $sql );
$cursor->execute( $datasent) ;

对于 $page 这将不起作用,因为它不是 WHERE 子句的一部分。相反,您应该只确保它包含一个数字,以防它来自外部。

die 'offset needs to be numeric' if $page =~ /\D/;

由于您是新用户,这里有一些关于您的代码的注意事项:

  • 总是 use strictuse warnings – 它们让您的生活更轻松
  • 然后用 my
  • 声明你的变量
  • $ALL_CAPS变量通常用于Perl中的全局变量
  • 在 DBI 上下文中,语句句柄通常命名为 $sth
  • 不要在 &foo() 中使用 & 符号,它不会像你想的那样
  • 您不需要将单个变量放入双引号中进行插值

除了@simbabque 的好建议之外,让我解释一下 + 替换。

全文搜索 BOOLEAN 模式,默认情况下可能不会执行您期望的操作。 "By default (when neither + nor - is specified) the word is optional, but the rows that contain it are rated higher... " 参见 Mysql Docs

因此,如果您的用户搜索 red apple,他们将获得带有 "red" 或 "apple" 的任何内容,优先级由 mysql 决定。您可能决定的可能不是他们想要的。所以在后端,你可以用 +red +apple 替换用户的搜索,这告诉 mysql 搜索 "red AND apple".

这就是我的

$datasent =~ s/[+\-<>)(]/ /g;     #These have special meaning in the sql search that people probably don't want.
$datasent =~ s/(".*?"|\S+)/+/g; #Add '+' for the boolean search and pay attention to quotes.