在Postgres中用字符串搜索连续的非相邻字符

时间:2018-11-20 16:34:10

标签: postgresql search fuzzy-search string-search

我想在postgres中复制类似command-t或Sublime“转到文件” / CMD + P搜索的内容。搜索匹配连续但不一定相邻的字符。像这样

enter image description here

这叫哪种模糊搜索?如果在postgres中无法做到这一点,那么在Elasticsearch或其他DB中是否可能?

所需的输出

例如,假设您的查询是“ doc”,则我期望以下顺序:

doc
d***o***c
d***oo**c
dpc
dppc
d***p***c
d
asdf
a

更新

使用ilike

with documents(title) as (
values
    ('d***o***c'),
    ('d***p***c'),
    ('d'),
    ('a'),
    ('dppc'),
    ('d***oo**c'),
    ('asdf'),
    ('dpc'),
    ('doc')
) select *
from documents
where title ilike '%d%o%c%';

实际输出

不订购相似性。在title上具有trigram索引,并且在30ms左右有700k行。

   title
-----------
 d***o***c
 d***oo**c
 doc

使用相似性

select title, similarity(title, 'doc') as sml
    from documents
    where similarity(title, 'doc') > 0
    order by sml desc
    limit 50;

实际输出

不区分非连续字母的优先级。在title上具有三字母索引,并且在30ms左右有700k行

   title   |   sml
-----------+----------
 doc       |        1
 d         |      0.2
 dpc       | 0.142857
 dppc      |    0.125
 d***o***c | 0.111111
 d***p***c | 0.111111
 d***oo**c |      0.1

使用Levenshtein

优先处理连续字母。在title上使用btree索引,在89ms左右的时间里有700k行

select levenshtein(title, 'doc', 30, 1, 60), title
    from documents
    where levenshtein(title, 'doc', 30, 1, 60) <= 500
    order by levenshtein(title, 'doc', 30, 1, 60)
    limit 50;

实际输出

 levenshtein |   title
-------------+-----------
           0 | doc
           6 | d***o***c
           6 | d***oo**c
          31 | dpc
          32 | dppc
          37 | d***p***c
          60 | d
          63 | asdf
          91 | a
(9 rows)

我的\timing结果并不是特别可靠,因为它们在我本地的16GB 2.5Ghz四核cpu上最多波动3秒,但它们可能有助于相对估计。

总体levenshtein是唯一产生预期结果的方法,但往往要慢得多,有时比其他方法慢5倍。我看不到任何有助于levenshtein方法的索引。

0 个答案:

没有答案