PostgreSQL中的全文搜索,基于每个关键字的不同分数具有自定义排名

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

有没有办法在PostgreSQL中“扩展” ts_rank函数或创建自定义setweight

我有2个表,recordstagsrecords可以有多个标签。使用表records_tags的多对多关联。 records_tags的列score表示同一标签的得分对每条记录都是不同的,并且在PostgreSQL的setweight中,权重可用的级别不仅仅是4个。

简化数据示例:

records

 id |         title          |             description
----+------------------------+--------------------------------------
  1 | 'The best record ever' | 'Long and meaningful description...'
  2 |       'Another record' | 'Description of the other record...'

tags

 id |           name
----+---------------------------
  1 | 'artificial intelligence'
  2 |        'machine learning'
  3 |            'life science'

records_tags

 record_id | tag_id | score
-----------+--------+-------
         1 |      1 |    87
         1 |      2 |    23
         2 |      1 |    54
         2 |      2 |    67
         2 |      3 |    90

这些表中的数据合并到另一个表search_documents中,该表具有列body作为jsonb类型,并包括每个记录的聚集标记名。

search_documents.body看起来像这样:

{
  title: 'The best record ever',
  description: 'Long and meaningful description...',
  tags: ['artificial intelligence', 'machine learning']
}

现在,我已经使用tsvector和setweight实现了全文搜索,如下所示:

setweight(to_tsvector('simple', (body ->> 'tags')), 'A') || ' ' ||
setweight(to_tsvector('english', (body ->> 'title')), 'B') || ' ' ||
setweight(to_tsvector('english', (body ->> 'description')), 'C')

以及类似的搜索查询:

SELECT
  ts_rank(sd.tsv, to_tsquery('english', ''' ' || :query || ' ''' || ':*'), 1) +
  ts_rank(sd.tsv, to_tsquery('simple', ''' ' || :query || ' ''' || ':*'), 1) AS rank
  sd.id AS id
FROM
  search_documents sd
WHERE
  sd.tsv @@ to_tsquery('english', ''' ' || :query || ' ''' || ':*') OR
  sd.tsv @@ to_tsquery('simple', ''' ' || :query || ' ''' || ':*')

但是它完全不允许我使用标签的分数。在计算score时,除了此以外,还有什么方法可以使用标签的rank吗?将records_tags.score也包括在search_documents.body中也不是问题,因为每个记录的内容都不同。

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

您可以使用setweight的3个参数形式来设置特定词素的权重,而不是将整个tsvector的所有权重设置为相同。大概您会将其内置到表“ search_documents”的创建过程中,但是由于您没有向我们展示该创建过程,因此我无法建议具体的实现。一旦有了正确加权的tsvector,就可以将其存储为单独的列,而不是存储在JSONB中。

© www.soinside.com 2019 - 2024. All rights reserved.