我需要使用全文搜索来获取列包含单词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"
,尽管搜索字符串已经转义。
我该如何解决这个问题?
答案 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
视为一个单词,你将不得不:
tsvector
和tsquery
剥离撇号。我会说第二种选择是迄今为止最简单的选择:
$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);