如何解决在全文搜索中按排名排序的正确方法?
我正在尝试通过 postgresql 中的多个相关模型字段实现全文搜索。
我的想法是使用 tsvector
将我需要搜索的所有字段放入一个连接的 to_tsvector(array_to_string(array[field1,field2,...],' ')
中,然后将其与实际搜索查询中的 tsquery
词素匹配。
我得到的 tsquery
是这样的:
select to_tsquery(string_agg(lexeme || ':*',' | ' order by positions)) as query
from unnest(to_tsvector('actual search query')).
为了匹配,我使用了 @@
运算符:select ... from ... where mytsvector @@ query
。
它似乎对我来说工作正常,但我注意到它并没有真正将行从最高匹配结果排序到最低匹配结果。因此,我尝试使用 ts_rank_cd
函数获取分数,然后添加 order by score DESC
。
然而,我得到的分数几乎总是 0
或 0.1
,很少有其他东西(例如 0.93251
等)。但是,即使那些高于 0.1
的分数似乎并不比许多其他具有 0.1
甚至 0
分数的人更好。这让我觉得我的排名方式不对。
我认为,通过连接我需要进行搜索的所有列,我可以同时为来自不同列的匹配项获得不错的排序搜索结果。
我将列与进一步匹配连接起来的想法至少可行吗?或者有更好的方法来做到这一点?
with search as (
select to_tsquery(string_agg(lexeme || ':*',' | ' order by positions)) as query
from unnest(to_tsvector('my search query'))
)
select
meeting.*,business.company as member_company,companydepartment.name as sp_company,ts_rank_cd(
to_tsvector(array_to_string(array[
"user".firstname,"user".lastname,"user".email,business.company,companydepartment.name,meeting.url,meeting.status,meeting.id::text
],' ')),query
) as score
from
search,meeting
join project on project.id = meeting.projectid
left join business on business.id = project.businessid
left join salesprofile on salesprofile.id = meeting.salesprofileid
left join companydepartment on salesprofile.id = companydepartment.salesprofileid
join "user" on "user".id = business.userid or "user".id = salesprofile.userid
where
to_tsvector(array_to_string(array[
"user".firstname,' '))
@@ query
group by
search.query,business.userid,meeting.id,salesprofile.userid,"user".firstname,"user".email
order by score desc;
我的排名是否正确?如果没有,那么我的错误在哪里以及如何解决?
PS:我想要实现的例子是这样的:
例如,我可以尝试按 meeting.status
、"user".email
和 business.company
进行搜索,并使用查询 accepted email@email.com Google
或 Facebook Rejected email+2@email.com
(以任意顺序)字)。我想首先获得符合所有三个条件的结果,然后是至少符合其中 2 个条件的结果,然后是至少符合其中一个条件的结果。
但是,通过这样的搜索查询和上面的 sql,我得到了一些随机排序(例如,结果的第一行可能只是状态为 accepted
的会议,第二行可能是状态为 {{1} 的会议} 和公司名称 accepted
等等,尽管 Google
)。
我还尝试在排名函数和 order by score
语句中执行 setweight
时使用 to_tsvector
,如下所示,这稍微改变了我的排名,但并没有真正改变这是我所期望的。
where
即使我将 ts_rank_cd(
to_tsvector(array_to_string(array[
meeting.url,' ')
|| setweight(to_tsvector('english',coalesce(meeting.status,'')),'A')
|| setweight(to_tsvector('english',coalesce(business.company,'B')
|| setweight(to_tsvector('english',coalesce(companydepartment.name,'B')
|| setweight(to_tsvector(coalesce("user".email,coalesce("user".firstname,'C')
|| setweight(to_tsvector('english',coalesce("user".lastname,'C')
),query
) as score
置于权重 meeting.status
,它的匹配度也没有比其他匹配高 A
。
我的方法正确吗?如果不是,如何更好地实现预期的功能?如果是,那么为什么我没有得到正确的(在我看来)排名?
PPS:我不能使用 status
或其他扩展。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。