PostgreSQL:在特定位置搜索部分单词

时间:2019-08-11 00:04:59

标签: regex postgresql

我正在尝试查找具有某些不同特征的歌曲名称。这些是条件:

  1. 歌曲名称由4个单词组成
  2. 每个单词的第一个字母是已知的(B%A%S%H%)

我将Musicbrainz数据作为postgres数据库,其中包含可查询的大量歌曲。我试图以几种方式查询数据,但没有得到想要的结果。

例如,下面的代码示例:

$strings = [ '12895 6 7 8 9', '2546734 34 55', '2334734556 341 5', ]; function formatNumber($number) { preg_match('/(\d+) ?((?:[\d]\s*){4})$/', $number, $matches); if (!$matches) { return $number; } return sprintf('%s %s', $matches[1], str_replace(' ', '', $matches[2])); } var_dump(array_map('formatNumber', $strings));

会让我半途而废,但这并不尊重我正在寻找的事实:

  1. 正好是4个字的歌曲标题
  2. 歌曲中每个单词的第一个字母必须与已知数据匹配(B%A%S%H%)

上面的查询(我知道这是错误的)会产生以下结果:

array(3) { [0] => string(10) "12895 6789" [1] => string(12) "2546734 3455" [2] => string(15) "2334734556 3415" }

select name from track where name ilike 'b% a% s% h%'

第一个是错误的,因为Brothers in Arms不满足第二个单词必须以“ A”开头并且总共必须包含4个单词的要求。

第二个单词是错误的,因为它不能满足总共需要四个单词的要求,即使前三个单词很匹配。

任何指针都值得赞赏!

1 个答案:

答案 0 :(得分:1)

您可以查看regular expressions。假设单词边界只能是一个空格(对于歌曲名称来说似乎是合理的),您可以尝试:

...
WHERE name ~* '^b[^ ]* a[^ ]* s[^ ]* h[^ ]*$'
...

第一个^匹配字符串的开头,$匹配字符串的结尾。 [^ ]是一个字符类,表示除空格以外的任何字符-^实际上是“否定”该类,或更准确地说,是其补语。也就是说,它匹配该类的任何字符。 *是一个量词,表示该类可以定义任意数量的字符,包括零。

如果存在多个空格字符,而不是多个空格序列的空格本身,请尝试:

...
WHERE name ~* '^b\S*\s+a\S*\s+s\S*\s+h\S*$'
...

\S\s还是字符类,但是是预定义的字符类。 \S表示任何字符,除非它是空白字符,而\s则是任何空白字符。