我在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中做到这一点?
不是分割成一个数组,而是分割成一个集合,然后重新组合,求和相似度
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)