从PostgreSQL全文搜索中获取匹配词位列表?

时间:2014-03-24 20:03:46

标签: postgresql

full text search ranking documentation暗示

  

您可以编写自己的排名功能和/或将其结果与其他因素结合起来,以满足您的特定需求。

但我还没有找到任何关于如何构建自定义排名功能的示例。

具体来说,我还没有弄清楚如何在tsvector中提取符合给定tsquery的词条列表......如下所示:

> SELECT ts_matching_lexemes('cat in the hat'::tsvector, 'cat'::tsquery);
ts_matching_lexems
------------------
'cat':1

那么,我怎样才能找出tsvector中哪个词位与给定的tsquery相匹配?

1 个答案:

答案 0 :(得分:2)

看起来ts_headline函数已在内部执行此操作,但它在c源代码深处并输出一个字符串。但是,您可以使用它来为字符串解析结果准备输入(与c函数相比,这相对较慢):

<强>代码:

CREATE OR REPLACE FUNCTION ts_matching_lexemes(tsv tsvector, tsq tsquery)
RETURNS TSVECTOR AS
$$

    WITH 
      proc AS (
        SELECT
            ts_headline(tsv::TEXT, tsq, 'StartSel = <;>, StopSel = <;>') tsh
    )
    , parts AS (
        SELECT unnest(regexp_split_to_array(tsh, '<;>')) p FROM proc
    )
    , parts_enum AS (
        SELECT p, lead(p, 1) OVER (), row_number() OVER () FROM parts
    )
    SELECT (string_agg(p || SUBSTRING(split_part(lead, ' ', 1) FROM 2), ' '))::tsvector
    FROM parts_enum
    WHERE row_number % 2 = 0

$$
LANGUAGE SQL;

<强> e.g:

select ts_matching_lexemes(to_tsvector('cat in the hat'), to_tsquery('cat'))
union
select ts_matching_lexemes(to_tsvector('cats and bikes in the hat'), to_tsquery('cat & bike'))


ts_matching_lexemes
tsvector
-------------------
'cat':1
'bike':3 'cat':1

<强> 注释

  1. tsvector的文字表示传递给ts_headline是为了减少冗余工作
  2. 它比ts_headline(text, to_tsquery(...))慢大约10倍,可以通过删除CTE来加速
  3. 当然,更快的解决方案是直接在c源中添加功能。这应该与tsvector @@ tsquery
  4. 一样快