PostgreSQL

时间:2015-04-29 05:02:37

标签: regex postgresql

我有一个Postgres数据库,其中包含带标签的视频。标签按字母顺序存储在以分号分隔的列表中。我希望能够使用标签列表查询数据库并返回匹配率最高的视频。

我看过使用regexp_match~和其他人。

到目前为止,我提出的最好的是一个平庸的启发式方法,用正则表达式搜索标签,即

SELECT FROM videos WHERE tags ~ 'kitten.*laser'

奖励(imo),这也会匹配fat-kittenbig-laser等标签

但问题在于,如果视频丢失了其中一个标签,而不是我在结果中没有得到的,并且如果用户选择的标签太多而不会看到任何视频。为了解决这个问题,我开始迭代我想要的视频数量并弹出不太相关的标签,但这最多是概率性的,最糟糕的是灾难。

我正在寻找的是某种Postgres查询,我可以在其中传递正则表达式并找到具有最大交集的videos的结果。

例如,让我们假装我们要查询以下数据:

cat;disaster;mouse
kitten;mouse;piano
cat;mouse;keyboard

标记cat, mouse, keyboard的最佳查询将按以下顺序返回行

cat;mouse;keyboard
cat;disaster;mouse
kitten;mouse;piano

因为第一行包含3个匹配,下一行包含2个匹配,最后一行包含一个匹配。

3 个答案:

答案 0 :(得分:0)

标签是经典的很多东西。是否可以将标签移动到自己的表中?您还需要一个包含标签和视频之间链接的连接表。抱歉,如果你出于某种原因通过这种方法,但我认为我会把它扔出去,因为它已经很好地旅行了。

答案 1 :(得分:0)

假设表:

create table tag (tags text);
insert into tag values
('cat;disaster;mouse'),
('kitten;mouse;piano'),
('cat;mouse;keyboard');

给定查询根据标记匹配计数对结果进行排序:

select 
  tags
from tag
order by 
  (select 
    sum(case t.tag in ('cat', 'mouse', 'keyboard') when true then 1 else 0 end) as match 
  from regexp_split_to_table(tags, ';') as t(tag) ) 
desc;

不幸

  

奖金(imo),这也将匹配像胖猫或小猫的标签   大激光

奖金已经消失,但也有可能重写一点来实现它。

答案 2 :(得分:0)

要查找带有标记的行,您可以使用Postgres的数组处理,这可能比正则表达式更有效。

select *
from tag
where string_to_array(tags, ';') && array['cat', 'mouse', 'keyboard'];

&&表示重叠 - 如果左侧和右侧至少有一个共同的元素,则返回该行。遗憾的是,数组没有“交叉”运算符,可以让您对结果进行排名。但是它不匹配fat-cat

通过在tags列上创建GiST索引可以改善上述情况,因为&&运算符可以使用这样的索引(但GiST索引构建比常规B树索引更昂贵)