类似于@willglynn 已经发布的内容,我会考虑pg_trgm模块。但最好使用GiST索引:
CREATE INDEX tbl_location_name_trgm_idx
USING gist(location_name gist_trgm_ops);
gist_trgm_ops
运算符类通常忽略大小写,并且ILIKE
与LIKE
. 引用源代码:
注意: IGNORECASE 宏意味着三元组不区分大小写。
我COLLATE "C"
在这里使用 - 这实际上不是特殊的排序规则(而是字节顺序),因为您的列中显然混合了各种排序规则。排序规则与排序或范围相关,对于基本的相似性搜索,您可以不用它。我会考虑COLLATE "C"
为您的专栏设置开始。
该索引将为您的第一个简单形式的查询提供支持:
SELECT * FROM tbl WHERE location_name ILIKE '%cafe%';
- 非常快。
- 保留查找部分匹配项的能力。
- 添加模糊搜索功能。
检查%
运算符和set_limit()
。
LIMIT n
GiST 索引对于选择 n 个“最佳”匹配的查询也非常快。您可以添加到上面的查询:
ORDER BY location_name <-> 'cafe'
LIMIT 20
<->
在此处的手册中阅读有关“距离”运算符的更多信息。
甚至:
SELECT *
FROM tbl
WHERE location_name ILIKE '%cafe%' -- exact partial match
OR location_name % 'cafe' -- fuzzy match
ORDER BY
(location_name ILIKE 'cafe%') DESC -- exact beginning first
,(location_name ILIKE '%cafe%') DESC -- exact partial match next
,(location_name <-> 'cafe') -- then "best" matches
,location_name -- break remaining ties (collation!)
LIMIT 20;
我在几个应用程序中使用类似的东西以获得(对我而言)令人满意的结果。当然,结合应用多个功能,它会变得有点慢。找到你的甜蜜点...
您可以更进一步,为每种语言创建一个单独的部分索引,并为每种语言使用匹配的排序规则:
CREATE INDEX location_name_trgm_idx
USING gist(location_name COLLATE "de_DE" gist_trgm_ops)
WHERE location_name_language = 'German';
-- repeat for each language
如果您只想要每个查询的特定语言的结果并且在这种情况下会非常快,那只会很有用。