5

我需要使用全文搜索来获取该列包含该单词的行 O'henry

我的代码:

$word = "O'henry";
$sql = "SELECT * FROM mytable WHERE to_tsvector('english', col) @@ to_tsquery(:word) ";

$sth = $db->prepare( $sql );
$sth->execute(
    array(":word"=>$word)
);

我有两个问题:

1) 此查询匹配包含单词 的列O'henry,但它也匹配包含例如:“O yes, thierry henry is good sportsman”的列。

2)如果$word以引号开头,例如'henry,我得到一个错误:syntax error in tsquery: "'henry",尽管搜索字符串已经被转义。

我怎么解决这个问题?

4

2 回答 2

4

默认的英语词典将对您的数据进行标记,将其'视为空格。您可以使用ts_debug检查 PostgreSQL/tsearch 将如何处理您的文本:

psql=# SELECT * FROM ts_debug('english','o''henry');
   alias   |   description   | token |  dictionaries  |  dictionary  | lexemes 
-----------+-----------------+-------+----------------+--------------+---------
 asciiword | Word, all ASCII | o     | {english_stem} | english_stem | {o}
 blank     | Space symbols   | '     | {}             |              | 
 asciiword | Word, all ASCII | henry | {english_stem} | english_stem | {henri}
(3 rows)

从这个输出中可以清楚地看出,如果你想让 postgres 被o'henry视为一个单词,你将不得不:

  • 创建一个自定义字典来处理带撇号的单词
  • tsvector在使用前和使用前去掉撇号tsquery

我想说第二种选择是迄今为止最简单的:

$sql = "SELECT * FROM mytable WHERE plainto_tsvector('english', replace(col, '''','')) @@ to_tsquery(replace(:word,'''',''));"
于 2013-05-13T19:32:36.637 回答
2

通读文档后,我认为这是to_tsquery. 根据此页面

to_tsquery 的输入必须已经遵循 tsquery 输入的一般规则

tsquery 输入规则在这里定义。根据给出的示例,引擎将每个输入单词处理为单引号字符串,这将中断您的输入。作为一种解决方法,我在这个论坛帖子中找到了一个建议(用户试图正确地转义输入'ksan

select *
from items
where to_tsvector(name) @@ to_tsquery(E'[\']ksan')

要将其应用于您的情况,您需要使用以下内容预先格式化您的输入:

$word = 'E' . str_replace("'", "[\']", $word);
于 2013-05-13T18:25:16.103 回答