“ts_headline”是否旨在突出显示查询的不匹配部分(确实如此)?

问题描述 投票:0回答:1

我在 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
的选项参数,但没有任何改变这种行为。

那么...我是否称其为错误,是否错误,或者我只是对其行为抱有错误的期望?

(似乎与这个旧问题无关,但它似乎描述了一个不同的错误。而且我无法判断在这个场景中究竟发生了什么、没有发生或应该发生什么,所以谁知道呢?是否相关。)

postgresql full-text-search
1个回答
0
投票

是的,

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 ;
其结果是:

我的标题我的查询有匹配吗敏捷的棕色狐狸跳过了懒惰的红狗假敏捷的棕色狐狸跳过了懒惰的狗真实
(Stackoverflow 从 PostgreSQL 结果中取出

<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') ;
我的标题我的查询有匹配吗敏捷的棕色狐狸跳过了懒惰的狗真实
如果您仍然希望通过不使用 WHERE 显示所有记录,即使是那些不匹配的记录,那么您可以使用如下序列:

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 ;
返回您所期望的内容(根据您的问题):

我的标题一些一些狗
红色
© www.soinside.com 2019 - 2024. All rights reserved.