首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Postgres word_similarity不比较单词

Postgres word_similarity不比较单词
EN

Stack Overflow用户
提问于 2017-10-27 01:54:01
回答 1查看 4.9K关注 0票数 9

“返回一个数字,表示第一个字符串与第二个字符串中最相似的单词有多相似。函数在第二个字符串中搜索一个最相似的单词,而不是一个最相似的子字符串。结果的范围是零(指示两个字符串完全不同)到一个字符串(指示第一个字符串与第二个字符串的一个单词相同)。”

这是word_similarity(a,b)的定义,据我所知,它将在文本b中查找单词a,将b拆分为单词,并获得最高匹配单词的分数。

然而,我看到了一些不一致的地方,其中的词匹配不是真正的词,看起来所有的曲线图是加扰和比较?

示例:

代码语言:javascript
复制
select word_similarity('sage', 'message sag')

返回1,显然“消息”或“凹陷”都不应该与“sage”匹配,但是如果我们将来自“message sag”的可能的trigram组合起来,我们就会发现“sage”中的所有trigram都是匹配的,但这并不是真正应该发生的情况,因为函数描述逐字逐句地谈论.是因为这两个词是相邻的吗?

如下所示,将返回0.6分:

代码语言:javascript
复制
select word_similarity('sage', 'message test sag') 

编辑:在http://sqlfiddle.com/#!17/b4bab/1周围玩小提琴

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-10-27 12:45:27

与描述不一致的函数

基于pgsql-bug邮件列表。的相关课题

子字符串相似算法提交人所述比较查询字符串和文本的三元数组。问题是优化了trigram数组(消除了重复的trigram),并丢失了有关文本中单个单词的信息。

该查询说明了这个问题:

代码语言:javascript
复制
with data(t) as (
values
    ('message'),
    ('message s'),
    ('message sag'),
    ('message sag sag'),
    ('message sag sage')
)

select 
    t as "text", 
    show_trgm(t) as "text trigrams", 
    show_trgm('sage') as "string trigrams", 
    cardinality(array_intersect(show_trgm(t), show_trgm('sage'))) as "common trgms"
from data;

       text       |                       text trigrams                       |       string trigrams       | common trgms 
------------------+-----------------------------------------------------------+-----------------------------+--------------
 message          | {"  m"," me",age,ess,"ge ",mes,sag,ssa}                   | {"  s"," sa",age,"ge ",sag} |            3
 message s        | {"  m","  s"," me"," s ",age,ess,"ge ",mes,sag,ssa}       | {"  s"," sa",age,"ge ",sag} |            4
 message sag      | {"  m","  s"," me"," sa","ag ",age,ess,"ge ",mes,sag,ssa} | {"  s"," sa",age,"ge ",sag} |            5
 message sag sag  | {"  m","  s"," me"," sa","ag ",age,ess,"ge ",mes,sag,ssa} | {"  s"," sa",age,"ge ",sag} |            5
 message sag sage | {"  m","  s"," me"," sa","ag ",age,ess,"ge ",mes,sag,ssa} | {"  s"," sa",age,"ge ",sag} |            5
(5 rows)    

最后三行中的trigram数组是相同的,包含查询字符串的所有trigram。

显然,实现与函数的描述不一致(在以后的文档版本中对描述进行了更改):

返回一个数字,该数字指示第一个字符串与第二个字符串中最相似的单词有多相似。函数在第二个字符串中搜索一个最相似的单词,而不是一个最相似的子字符串。

我在上面的查询中使用的函数:

代码语言:javascript
复制
create or replace function public.array_intersect(anyarray, anyarray)
returns anyarray language sql immutable
as $$
    select case 
        when $1 is null then $2
        else
            array(
                select unnest($1)
                intersect
                select unnest($2)
            )
        end;
$$;

解决办法

您可以轻松地编写自己的函数以获得更多的预期结果:

代码语言:javascript
复制
create or replace function my_word_similarity(text, text)
returns real language sql immutable as $$
    select max(similarity($1, word))
    from regexp_split_to_table($2, '[^[:alnum:]]') word
$$;

比较:

代码语言:javascript
复制
with data(t) as (
values
    ('message'),
    ('message s'),
    ('message sag'),
    ('message sag sag'),
    ('message sag sage')
)

select t, word_similarity('sage', t), my_word_similarity('sage', t)
from data;

        t         | word_similarity | my_word_similarity
------------------+-----------------+--------------------
 message          |             0.6 |                0.3
 message s        |             0.8 |                0.3
 message sag      |               1 |                0.5
 message sag sag  |               1 |                0.5
 message sag sage |               1 |                  1
(5 rows)

Postgres 11+中的新函数

Postgres 11+ strict_word_similarity()中有一个新的函数,它给出了问题作者期望的结果:

代码语言:javascript
复制
with data(t) as (
values
    ('message'),
    ('message s'),
    ('message sag'),
    ('message sag sag'),
    ('message sag sage')
)

select t, word_similarity('sage', t), strict_word_similarity('sage', t)
from data;

        t         | word_similarity | strict_word_similarity
------------------+-----------------+------------------------
 message          |             0.6 |                    0.3
 message s        |             0.8 |             0.36363637
 message sag      |               1 |                    0.5
 message sag sag  |               1 |                    0.5
 message sag sage |               1 |                      1
(5 rows)
票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46966360

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档