为什么此 postgresql 全文搜索查询返回 ts_rank of 0?
why is this postgresql full text search query returning ts_rank of 0?
在我投资使用 solr 或 lucene 或 sphinx 之前,我想尝试使用 postgresql 全文搜索在我的系统上实现搜索功能。
我在 table 中有一份全国企业列表,我想搜索。我创建了一个结合了公司名称和城市的 ts 向量,这样我就可以像 "outback atlanta" 这样进行搜索。
我还通过在搜索模式中附加“:”并在关键字之间插入“&”来使用搜索的通配符功能实现自动完成功能,因此搜索模式"outback atl" 在使用 to_tsquery().
转换为查询之前变成 "outback & atl:"
这是我目前运行正在解决的问题。
如果搜索模式输入为 "ou",则会返回许多 "Outback Steakhouse" 条记录。
如果搜索模式输入为 "out",则不会返回任何结果。
如果搜索模式输入为 "outb",则会返回许多 "Outback Steakhouse" 条记录。
做了一点调试,我想到了这个:
select ts_rank(to_tsvector('Outback Steakhouse'),to_tsquery('ou:*')) as "ou",
ts_rank(to_tsvector('Outback Steakhouse'),to_tsquery('out:*')) as "out",
ts_rank(to_tsvector('Outback Steakhouse'),to_tsquery('outb:*')) as "outb"
结果如下:
ou out outb
0.0607927 0 0.0607927
我做错了什么?
这是pg全文搜索的限制吗?
我可以用我的字典或配置来解决这个异常吗?
更新:
我认为 "out" 可能是停用词。
当我 运行 这个调试查询时,我没有得到 "out"
的任何词位
SELECT * FROM ts_debug('english','out back outback');
alias description token dictionaries dictionary lexemes
asciiword Word all ASCII out {english_stem} english_stem {}
blank Space symbols {}
asciiword Word all ASCII back {english_stem} english_stem {back}
blank Space symbols {}
asciiword Word all ASCII outback {english_stem} english_stem {outback}
所以现在请问如何修改停用词列表来删除一个词?
更新:
这是我目前使用的查询:
select id,name,address,city,state,likes
from view_business_favorite_count
where textsearchable_index_col @@ to_tsquery('simple',)
ORDER BY ts_rank(textsearchable_index_col, to_tsquery('simple',)) DESC
当我执行查询时(我使用的是 Strongloop Loopback + Express + Node),我将模式传入以替换 $1 参数。模式(如上所述)看起来像 "keyword:" 或 "keyword1 & keyword2 & ... & keywordN:"
谢谢
这里的问题是您正在搜索 企业名称 并且正如@Daniel 正确指出的那样 - 'english'
字典不会帮助您找到 "fuzzy" 匹配非字典词,如 "Outback Steakhouse" 等;
'simple'
字典
'simple'
字典本身对您也没有帮助,在您的情况下 企业名称 仅适用于 完全匹配 因为所有的词都是无词干的。
'simple'
字典+pg_trgm
但是,如果您将 'simple'
字典与 和 pg_trgm
模块一起使用 - 它正是您所需要的,特别是:
- 对于
to_tsvector('simple','<business name>')
你不需要担心停用词"hack",你会得到所有的词素;
- 使用
pg_trgm
中的 similarity()
你会得到最高的 "rank"
为了获得最佳匹配,
看看这个:
WITH pg_trgm_test(business_name,search_pattern) AS ( VALUES
('Outback Steakhouse','ou'),
('Outback Steakhouse','out'),
('Outback Steakhouse','outb')
)
SELECT business_name,search_pattern,similarity(business_name,search_pattern)
FROM pg_trgm_test;
结果:
business_name | search_pattern | similarity
--------------------+----------------+------------
Outback Steakhouse | ou | 0.1
Outback Steakhouse | out | 0.15
Outback Steakhouse | outb | 0.2
(3 rows)
通过 similarity
订购 DESC
您将能够得到您所需要的。
更新
对于您的情况,有 2 种可能的选择。
选项#1。
只需为 view_business_favorite_count
table 中的 name
列创建 trgm 索引;索引定义可能如下:
CREATE INDEX name_trgm_idx ON view_business_favorite_count USING gin (name gin_trgm_ops);
查询看起来像这样:
SELECT
id,
name,
address,
city,
state,
likes,
similarity(name,) AS trgm_rank -- similarity score
FROM
view_business_favorite_count
WHERE
name % -- trgm search
ORDER BY trgm_rank DESC;
选项#2。
使用全文搜索,您需要:
- 创建一个单独的 table,例如
unnested_business_names
,您将在其中存储 2 列:第 1 列将保留 all 来自 [=29= 的词素] 函数,第二列将有 vbfc_id
(FK for id
from view_business_favorite_count
table);
- 为包含词位的列添加
trgm
索引;
- 为
unnested_business_names
添加触发器,它将更新或插入或删除 view_business_favorite_count
中的新值以使所有单词保持最新
在我投资使用 solr 或 lucene 或 sphinx 之前,我想尝试使用 postgresql 全文搜索在我的系统上实现搜索功能。
我在 table 中有一份全国企业列表,我想搜索。我创建了一个结合了公司名称和城市的 ts 向量,这样我就可以像 "outback atlanta" 这样进行搜索。
我还通过在搜索模式中附加“:”并在关键字之间插入“&”来使用搜索的通配符功能实现自动完成功能,因此搜索模式"outback atl" 在使用 to_tsquery().
转换为查询之前变成 "outback & atl:"这是我目前运行正在解决的问题。 如果搜索模式输入为 "ou",则会返回许多 "Outback Steakhouse" 条记录。 如果搜索模式输入为 "out",则不会返回任何结果。 如果搜索模式输入为 "outb",则会返回许多 "Outback Steakhouse" 条记录。
做了一点调试,我想到了这个:
select ts_rank(to_tsvector('Outback Steakhouse'),to_tsquery('ou:*')) as "ou",
ts_rank(to_tsvector('Outback Steakhouse'),to_tsquery('out:*')) as "out",
ts_rank(to_tsvector('Outback Steakhouse'),to_tsquery('outb:*')) as "outb"
结果如下:
ou out outb
0.0607927 0 0.0607927
我做错了什么?
这是pg全文搜索的限制吗?
我可以用我的字典或配置来解决这个异常吗?
更新: 我认为 "out" 可能是停用词。
当我 运行 这个调试查询时,我没有得到 "out"
的任何词位SELECT * FROM ts_debug('english','out back outback');
alias description token dictionaries dictionary lexemes
asciiword Word all ASCII out {english_stem} english_stem {}
blank Space symbols {}
asciiword Word all ASCII back {english_stem} english_stem {back}
blank Space symbols {}
asciiword Word all ASCII outback {english_stem} english_stem {outback}
所以现在请问如何修改停用词列表来删除一个词?
更新: 这是我目前使用的查询:
select id,name,address,city,state,likes
from view_business_favorite_count
where textsearchable_index_col @@ to_tsquery('simple',)
ORDER BY ts_rank(textsearchable_index_col, to_tsquery('simple',)) DESC
当我执行查询时(我使用的是 Strongloop Loopback + Express + Node),我将模式传入以替换 $1 参数。模式(如上所述)看起来像 "keyword:" 或 "keyword1 & keyword2 & ... & keywordN:"
谢谢
这里的问题是您正在搜索 企业名称 并且正如@Daniel 正确指出的那样 - 'english'
字典不会帮助您找到 "fuzzy" 匹配非字典词,如 "Outback Steakhouse" 等;
'simple'
字典
'simple'
字典本身对您也没有帮助,在您的情况下 企业名称 仅适用于 完全匹配 因为所有的词都是无词干的。
'simple'
字典+pg_trgm
但是,如果您将 'simple'
字典与 和 pg_trgm
模块一起使用 - 它正是您所需要的,特别是:
- 对于
to_tsvector('simple','<business name>')
你不需要担心停用词"hack",你会得到所有的词素; - 使用
pg_trgm
中的similarity()
你会得到最高的 "rank" 为了获得最佳匹配,
看看这个:
WITH pg_trgm_test(business_name,search_pattern) AS ( VALUES
('Outback Steakhouse','ou'),
('Outback Steakhouse','out'),
('Outback Steakhouse','outb')
)
SELECT business_name,search_pattern,similarity(business_name,search_pattern)
FROM pg_trgm_test;
结果:
business_name | search_pattern | similarity
--------------------+----------------+------------
Outback Steakhouse | ou | 0.1
Outback Steakhouse | out | 0.15
Outback Steakhouse | outb | 0.2
(3 rows)
通过 similarity
订购 DESC
您将能够得到您所需要的。
更新
对于您的情况,有 2 种可能的选择。
选项#1。
只需为 view_business_favorite_count
table 中的 name
列创建 trgm 索引;索引定义可能如下:
CREATE INDEX name_trgm_idx ON view_business_favorite_count USING gin (name gin_trgm_ops);
查询看起来像这样:
SELECT
id,
name,
address,
city,
state,
likes,
similarity(name,) AS trgm_rank -- similarity score
FROM
view_business_favorite_count
WHERE
name % -- trgm search
ORDER BY trgm_rank DESC;
选项#2。
使用全文搜索,您需要:
- 创建一个单独的 table,例如
unnested_business_names
,您将在其中存储 2 列:第 1 列将保留 all 来自 [=29= 的词素] 函数,第二列将有vbfc_id
(FK forid
from view_business_favorite_count
table); - 为包含词位的列添加
trgm
索引; - 为
unnested_business_names
添加触发器,它将更新或插入或删除view_business_favorite_count
中的新值以使所有单词保持最新