Postgres和全文搜索:搜索带有多个否定短语的短语的正确SQL查询是什么?

时间:2019-07-03 11:42:21

标签: postgresql full-text-search

我有一个带有description列的表。

在此表中,我添加了一个名为tsv的额外列,其中填充了说明的tsvector。

我正在尝试在tsv列中查询某个短语,但添加否定短语以减少返回的误报数量,但是我不确定在得到正确答案后该怎么做我尝试的每种方式返回的结果数量不同。

例如,像在一条小河里一样,沿河流走。

我明白了

WHERE tsv @@ to_tsquery('english', '
        stream
    ')

RETURNS: 26

但是在一些描述中,因为我已经手动检查了全部26个,所以他们只谈论:

  

...光从两个窗口进入...(其中有1个)

  

...自然光流...   (其中有2个)

与一点流水无关。

总共3个,所以我希望可以返回23个。

这是我到目前为止尝试过的,没有一个返回23:

WHERE tsv @@ to_tsquery('english', '
        stream
        & ! light<->streaming
        | ! stream<2>natural<->light
    ')

>RETURNS: 261

WHERE tsv @@ to_tsquery('english', '
        stream
        & ! light<->streaming
        & ! stream<2>natural<->light
    ')

>RETURNS: 3

WHERE tsv @@ to_tsquery('english', '
        stream
        & ! ( 
            light<->streaming
            | stream<2>natural<->light
        )
    ')

>RETURNS: 8

WHERE tsv @@ to_tsquery('english', '
        stream
        & ( 
            ! light<->streaming
            | ! stream<2>natural<->light
        )
    ')

>RETURNS: 26

我在做什么错? 还是我需要一种完全不同的方式?

预先感谢

添加

所以我肯定并且出于理智地知道,我为要否定的每个术语都按了这段代码

WHERE tsv @@ to_tsquery('english',
        'light<->streaming'
     )

>RETURNS: 1
WHERE tsv @@ to_tsquery('english',
        'stream<2>natural<->light'
     )

>RETURNS: 2

两个都返回了我要从主查询中删除的记录。

2 个答案:

答案 0 :(得分:0)

取反运算符!的绑定强度比<->强,因此您必须正确使用括号:

... WHERE tsv @@ to_tsquery(
                    'english',
                    'stream
                     & !(light <-> stream)
                     & !(stream <2> natural <-> light)'
                 );

答案 1 :(得分:0)

跟进

我无法以尝试的方式解决此问题 例如全部都放在一个子句中。

为了解决这个问题,我为每个取反项创建了单独的where子句。

所以不是

...  
WHERE tsv @@ to_tsquery('english',
                        'stream
                         & !(light <-> stream)
                         & !(stream <2> natural <-> light)'
                     );

我改为这样做

...
WHERE tsv @@ to_tsquery('english','stream')
AND NOT WHERE tsv @@ to_tsquery('english','light <-> stream')
AND NOT WHERE tsv @@ to_tsquery('english','stream <2> natural <-> light')

以这种方式进行操作产生了我期望的结果。

希望这可以帮助遇到相同问题的人。