我有一个Postgres数据库,其中包含带标签的视频。标签按字母顺序存储在以分号分隔的列表中。我希望能够使用标签列表查询数据库并返回匹配率最高的视频。
我看过使用regexp_match
,~
和其他人。
到目前为止,我提出的最好的是一个平庸的启发式方法,用正则表达式搜索标签,即
SELECT FROM videos WHERE tags ~ 'kitten.*laser'
奖励(imo),这也会匹配fat-kitten
或big-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个匹配,最后一行包含一个匹配。
答案 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树索引更昂贵)