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

时间:2013-05-13 18:04:08

标签: php postgresql

我需要使用全文搜索来获取列包含单词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是好运动员。”

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

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:3)

默认的英语词典会将'处理的数据标记为空格。您可以使用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,'''',''));"

答案 1 :(得分:1)

阅读完文档后,我认为这是to_tsquery接受的字符串类型的限制。根据{{​​3}}:

  

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

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

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

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

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