我正在开发一个多租户 Web 应用程序,我想添加全文搜索,以便人们能够:
1) 仅搜索他们当前访问的站点(但不是所有站点),以及
2) 仅搜索该站点的一部分(例如,将搜索限制为站点上的博客或论坛),以及
3) 搜索单个论坛主题只要。
我想知道我应该添加哪些索引?
请假设数据库很大(例如,按站点 ID 进行索引扫描,然后按全文搜索进行过滤太慢了)。
我可以想到三种方法:
创建三个索引。1) 一个基于每个站点索引所有内容的索引。和 2) 一个在每个站点加上站点部分的基础上索引所有内容的索引。3) 一个基于每个站点和页面 ID 索引所有内容的索引。
创建一个单一索引,并在 [要索引的文本] 中插入魔术词,例如:“site_<site-id>”和“section_<section-id>”和“page_<page-id>”,然后当我搜索对于站点 YYY 中的第 XX 部分,我可以像这样为搜索查询添加前缀:“site_XX AND section_YYY AND ...”。
创建新站点或站点部分时动态添加数据库索引:
create index dw1_posts__search_site_YYY on dw1_posts using gin(to_tsvector('english', approved_text)) where site_id = 'YYY';
以上这三种方法中的任何一种都有意义吗?有更好的选择吗?
(详细信息:但是,也许方法 1 是不可能的?尝试同时索引列和索引全文搜索,会导致语法错误:
> create index dw1_posts__search_site
on dw1_posts (site_id)
using gin(to_tsvector('english', approved_text));
ERROR: syntax error at or near "using"
LINE 1: ...dex dw1_posts__search_site on dw1_posts(site_id) using gin(...
^
> create index dw1_posts__search_site
on dw1_posts
using gin(to_tsvector('english', approved_text))
(site_id);
ERROR: syntax error at or near "("
LINE 1: ... using gin(to_tsvector('english', approved_text)) (site_id);
(如果方法 1可行,那么我可以进行如下查询:
select ... from ... where site_id = ... and <full-text-search-column> @@ <query>;
并让 PostgreSQL 首先检查 site_id,然后使用一个索引检查全文搜索列。))
/结束详细信息。)
一周后更新:我改用ElasticSearch。我的印象是,对于分面搜索,关系数据库/PostgreSQL 不存在可扩展的解决方案。与 ElasticSearch 集成似乎与实施、测试和调整此处建议的方法一样简单。(例如,PostgreSQL 的词干分析器/不管它叫什么,可能会将“section_NNN”拆分为两个词:“section”和“NNN”,从而索引页面上不存在的词!修复这些烦人的小问题很棘手。)