如何在Postgres中执行简单的地图缩减?

use*_*521 6 postgresql

我在postgres中使用trigrams进行全文搜索,如下所示:

SELECT * 
FROM "Users" users 
WHERE 'search_text' % ANY(regexp_split_to_array(users.name,E'\\s+'))
Run Code Online (Sandbox Code Playgroud)

上面的查询检查是否search_text匹配任何单词(拆分whitespace)User.displayName.这可行,但结果不按实际"得分"排序.

分数可以通过similarity(text,text)函数计算.

问题是,我必须按顺序排列每个单词的所有相似之处User.name.因此,如果用户名是,"A B C"则其分数应为:

similarity('search_text','A') + similarity('search_text','B') + similarity('search_text','C')
Run Code Online (Sandbox Code Playgroud)

所以我需要将用户名字映射到分数,然后对它们求和(减少).我怎样才能在postgres中做到这一点?

Clo*_*eto 4

不是分割成一个数组,而是分割成一个集合,然后重新组合,求和相似度

with users as (
    select user_id, name
    from (values (1, 'John Smith')) t(user_id, name)
)
select user_id, sum(similarity('smth', name_part))
from (
    select user_id, regexp_split_to_table(name, E'\\s+') as name_part
    from users
) users
where 'smth' % name_part
group by user_id
order by 2 desc
;
 user_id |  sum  
---------+-------
       1 | 0.375
Run Code Online (Sandbox Code Playgroud)

我不确定您是否想要消除那些相似度低于阈值的名称部分。如果不是,则省略该where子句

顺便说一句,为什么需要拆分名称?为什么不直接将整个名称与搜索字符串进行比较呢?

with users as (
    select user_id, name
    from (values (1, 'John Smith')) t(user_id, name)
)
select similarity('jon smth', name), *
from users
order by 1 desc
;
 similarity | user_id |    name    
------------+---------+------------
   0.333333 |       1 | John Smith
Run Code Online (Sandbox Code Playgroud)