我在 Postgres 13.4 中运行一些复杂的 FTS 查询,并发现
ts_headline
中的一些行为是出乎意料的,至少对我来说是这样,并且不确定我是否遇到了功能或错误。 ;)
初始健全性检查:
SELECT plainto_tsquery('english', 'red dog') @@ to_tsvector('The quick brown fox jumped over the lazy dog.');
-- false
毫不奇怪:
tsquery
的计算结果为'red' & 'dog'
,文档不包含'red'
,不匹配。 但当我试图成为头条新闻时:
SELECT ts_headline('The quick brown fox jumped over the lazy dog.', plainto_tsquery('english', 'red dog'));
-- The quick brown fox jumped over the lazy <b>dog</b>.
FOLLOWED_BY 运算符也会发生同样的情况 (
<->
);您可以将 plainto_tsquery
替换为 phraseto_tsquery
(或构造您自己的 tsquery
文字)。 它仍然突出显示实际上不匹配的片段。
问题不是(或者至少不完全是)在没有真正匹配的情况下尝试调用
ts_headline
的结果。 我原来的情况其实更像是:
SELECT ts_headline('I want a red dog, but not a black dog. No red cats, either.', phraseto_tsquery('english', 'red dog'));
-- I want a <b>red</b> <b>dog</b>, but not a black <b>dog</b>. No <b>red</b> cats, either.
在这种情况下,考虑到
tsquery
的计算结果为 'red' <-> 'dog'
(即“红色”紧接着“狗”),我对最后两个亮点感到惊讶。
ts_headline
的文档说:
以缩写形式显示文档中查询的匹配,
这让我相信这是一个错误,但是突出显示结果的较长简介仅说明了功能
返回文档的摘录,其中突出显示查询中的术语
事实上,查询中的术语是突出显示...
我尝试过修改
ts_headline
的选项参数,但没有任何改变这种行为。
那么...我是否称其为错误,它是否错误,或者我只是对其行为抱有错误的期望?
(似乎与这个旧问题无关,但它似乎描述了一个不同的错误。而且我无法判断在这个场景中究竟发生了什么、没有发生或应该发生什么,所以谁知道呢?是否相关。)
是的,
ts_headline
旨在突出显示查询中不匹配的部分。这不是一个错误,它的工作方式如文档中所宣传的那样:
该函数将使用查询来选择相关的文本片段,并且 然后突出显示查询中出现的所有单词,即使这些单词 位置与查询的限制不匹配为了更好地了解它,请查看以下查询:
SELECT ts_headline('The quick brown fox jumped over the lazy dog.',
plainto_tsquery('english', 'red dog')) AS my_headline,
'red dog' as my_query,
'The quick brown fox jumped over the lazy dog.'
@@ plainto_tsquery('english', 'red dog') AS is_there_a_match
UNION ALL
SELECT ts_headline('The quick brown fox jumped over the lazy dog.',
plainto_tsquery('english', 'red dog')) AS my_headline,
'dog' AS my_query,
'The quick brown fox jumped over the lazy dog.'
@@ plainto_tsquery('english', 'dog') AS is_there_a_match
;
其结果是:
狗。 | ||
狗。 |
<b>dog</b>
,并在此处将其变为粗体。)如果只想得到与查询匹配的记录,则需要 WHERE 条件。以下内容不返回任何记录:
SELECT ts_headline('The quick brown fox jumped over the lazy dog.',
plainto_tsquery('english', 'red dog')) AS my_headline,
'red dog' as my_query,
'The quick brown fox jumped over the lazy dog.'
@@ plainto_tsquery('english', 'red dog') AS is_there_a_match
WHERE 'The quick brown fox jumped over the lazy dog.'
@@ plainto_tsquery('english', 'red dog');
虽然这显示了一条记录:
SELECT ts_headline('The quick brown fox jumped over the lazy dog.',
plainto_tsquery('english', 'red dog')) AS my_headline,
'dog' AS my_query,
'The quick brown fox jumped over the lazy dog.'
@@ plainto_tsquery('english', 'dog') AS is_there_a_match
WHERE 'The quick brown fox jumped over the lazy dog.'
@@ plainto_tsquery('english', 'dog')
;
狗。 |
CASE WHEN my_document @@ plainto_tsquery('english', 'red dog')
THEN ts_headline(my_document, plainto_tsquery('english', 'red dog'))
ELSE my_document
END AS my_headline
相关的独立查询(您可以在没有表的情况下进行测试)是:
SELECT CASE WHEN 'some red dogs' @@ plainto_tsquery('english', 'red dog')
THEN ts_headline('some red dogs', plainto_tsquery('english', 'red dog'))
ELSE 'some red dogs'
END AS my_headline
UNION ALL
SELECT CASE WHEN 'some dogs' @@ plainto_tsquery('english', 'red dog')
THEN ts_headline('some dogs', plainto_tsquery('english', 'red dog'))
ELSE 'some dogs'
END AS my_headline
;
返回您所期望的内容(根据您的问题):
红色狗 |