postgresql全文搜索的问题,包含单引号


Problems at postgresql full text search with words, containing single quotes

我需要使用全文搜索来获取列中包含单词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",尽管搜索字符串已经被转义了。

我该如何解决这个问题?

默认英语字典将把您的数据标记为将'视为一个空格。你可以使用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视为单个单词,您将不得不:

  • 创建一个自定义字典来处理带有撇号的单词
  • 在使用tsvectortsquery之前去掉撇号。

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

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

通读文档后,我认为这是to_tsquery接受的字符串类型的限制。根据本页:

to_tsquery的输入必须已经遵循通用规则tsquery输入

查询输入规则在这里定义。根据给出的示例,引擎将每个输入单词处理成单引号字符串,这些字符串将在输入时中断。作为解决方案,我在这个论坛帖子中发现了一个建议(用户试图正确地转义输入'ksan:

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

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

$word = 'E' . str_replace("'", "['']", $word);