2014-12-03 4 views
5

Я использую триграммы для полнотекстового поиска в Postgres, как это:Как выполнить простую карту в Postgres?

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

запрос выше проверок, если 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') 

Так что мне нужно, чтобы отобразить имя пользователя слов баллов, а затем сумму (уменьшить) их. Как я могу это сделать в postgres?

ответ

1

В вместо расщепления на массив разделен на набор затем перегруппировку суммирования схожести

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 

Я не уверен, что вы хотите, чтобы устранить эти части имен, для которых сходство ниже порогового значения. Если не просто опустить пункт 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 
Смежные вопросы