postgreSQL全文搜索中的自定义排名

Kir*_*ran 7 postgresql

当内置的ts_rank和ts_rank_cd函数不足时,Postgresql文档提到了自定义排名函数.有没有任何文档/示例如何实现?

来自postgres文档 - 内置的排名功能仅是示例.您可以编写自己的排名功能和/或将其结果与其他因素结合起来,以满足您的特定需求.

小智 2

原文的定义ts_rank(tsvector,tsquery)是:

CREATE OR REPLACE FUNCTION pg_catalog.ts_rank(tsvector, tsquery)
 RETURNS real
 LANGUAGE internal
 IMMUTABLE PARALLEL SAFE STRICT
AS $function$ts_rank_tt$function$
Run Code Online (Sandbox Code Playgroud)

因此,我们可以简单地定义一个函数,将 tsvector 和 tsquery 作为输入并返回实数。按照惯例,结果越高,排名就越高。

因此,我们可以轻松创建自己的函数(使用 PostgreSQL 12 进行测试):

CREATE OR REPLACE FUNCTION public.ts_rank_custom(v tsvector, q tsquery)
 RETURNS real
 LANGUAGE plpgsql
 IMMUTABLE PARALLEL SAFE STRICT
AS $function$
        DECLARE 
                subtotal REAL;
                ta text[];
                i bigint;
        BEGIN
                SELECT INTO subtotal ts_rank(v,q);

                ta = tsvector_to_array(v);

                FOR i IN 1 .. array_upper(ta,1)
                LOOP
                 IF length(ta[i])<4 THEN
                  subtotal = subtotal * 1.1;
                 END IF;
                END LOOP;
                RETURN subtotal;
        END;
        $function$;
Run Code Online (Sandbox Code Playgroud)

我们的函数将原始值ts_rank作为起始值,然后对于 tsvector 中每个短于 4 个字符的标记(我们喜欢短单词)将其增加 10%。

以下是我们的测试数据的示例结果:

# SELECT ts,ts_rank(ts,query),ts_rank_custom(ts,query)
        FROM bench,to_tsquery('english','dog') as query
        WHERE query @@ ts order by 3 desc;
                                                             ts                                                              |  ts_rank   | ts_rank_custom 
-----------------------------------------------------------------------------------------------------------------------------+------------+----------------
 'bet' 'bunnies' 'dog' 'heaps' 'potluck' 'purus' 'respires' 'shininess' 'viennese'                                           | 0.06079271 |     0.07355918
 'antagonizing' 'are' 'broths' 'discontinuing' 'dog' 'estuary' 'rosins' 'tanzania'                                           | 0.06079271 |     0.07355918
 'borderlines' 'brunei' 'cutthroat' 'dog' 'ego' 'herrick' 'neptunium' 'scoffs'                                               | 0.06079271 |     0.07355918
 'clock' 'decrescendos' 'dog' 'obsolete' 'peg' 'robocalls' 'rote' 'rousing' 'wabash'                                         | 0.06079271 |     0.07355918
 'absenting' 'comfortingly' 'dog' 'laurence' 'mascots' 'monitors' 'properest' 'scratch' 'terrific' 'unsoundest' 'victualled' | 0.06079271 |     0.06687198
 'advocates' 'angiosperm' 'dog' 'embarrassments' 'leafleting' 'sacrileges' 'toneless' 'whets'                                | 0.06079271 |     0.06687198
 'creeping' 'dissembles' 'distaste' 'dog' 'escapee' 'excusable' 'mickey' 'noose' 'onus' 'physiologists' 'taklamakan'         | 0.06079271 |     0.06687198
 'abusive' 'buddhists' 'comedienne' 'dog' 'gust' 'opts' 'pressed'                                                            | 0.06079271 |     0.06687198
 'chungking' 'depositor' 'dog' 'jutted' 'nothings' 'warfare'                                                                 | 0.06079271 |     0.06687198
 'aconite' 'dog' 'domesticity' 'dowdies' 'pupils' 'undistinguished'                                                          | 0.06079271 |     0.06687198
 'contaminant' 'disinters' 'dog' 'embroidery' 'huskiest' 'lender' 'outlines' 'oversize' 'professor' 'tractors'               | 0.06079271 |     0.06687198
 'dog' 'leavens' 'overtly' 'plucked' 'transfigure'                                                                           | 0.06079271 |     0.06687198
(12 rows)
Run Code Online (Sandbox Code Playgroud)

您可以看到我们的 ts_rank_custom 更喜欢单词较短的条目。

基本上,您可以在具有给定签名的函数内实现您想要的任何排名逻辑,并使用它而不是标准 ts_rank* 函数。