0

我正在开发一个多租户 Web 应用程序,我想添加全文搜索,以便人们能够:

1) 仅搜索他们当前访问的站点(但不是所有站点),以及
2) 仅搜索该站点的一部分(例如,将搜索限制为站点上的博客或论坛),以及
3) 搜索单个论坛主题只要。

我想知道我应该添加哪些索引?

请假设数据库很大(例如,按站点 ID 进行索引扫描,然后按全文搜索进行过滤太慢了)。

我可以想到三种方法:

  1. 创建三个索引。1) 一个基于每个站点索引所有内容的索引。和 2) 一个在每个站点加上站点部分的基础上索引所有内容的索引。3) 一个基于每个站点和页面 ID 索引所有内容的索引。

  2. 创建一个单一索引,并在 [要索引的文本] 中插入魔术词,例如:“site_<site-id>”和“section_<section-id>”和“page_<page-id>”,然后当我搜索对于站点 YYY 中的第 XX 部分,我可以像这样为搜索查询添加前缀:“site_XX AND section_YYY AND ...”。

  3. 创建新站点或站点部分时动态添加数据库索引:

     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”,从而索引页面上不存在的词!修复这些烦人的小问题很棘手。)

4

2 回答 2

1

正常的方法是创建:

  • 一个全文索引:

    在 dw1_posts 上使用 gin(to_tsvector('english',approved_text)) 创建索引 idx1;

  • site_id 上的简单索引:

    在 dw1_posts(page_id) 上创建索引 idx2;

  • page_id 上的另一个简单索引:

    在 dw1_posts(site_id) 上创建索引 idx3;

然后,SQL 计划者的工作就是根据查询和列中值的分布来决定使用哪些(如果有)以及以什么顺序使用。在您真正目睹缓慢的查询之前,试图智取规划器是没有意义的。

于 2013-07-13T17:30:38.953 回答
0

另一种替代方法,类似于“site_<site-id>”、“section_<section-id>”和“page_<page-id>”替代方法,应该在要索引的文本前加上:

SiteSectionPage_<site-id>_<section-id>_<subsection-id>_<page-id>

然后在搜索时使用前缀匹配(即:*

select ... from .. where .. @@ 'SiteSectionPage_NN_MMM:* AND (the search phrase)'

其中 NN 是站点 ID,MMM 是部分 ID。

但这不适用于中文?我认为在索引中文时使用三元组是合适的,但是 SiteSectionPage... 将被拆分为:Sit, ite, teS, eSe,这没有任何意义。

于 2013-07-14T03:34:43.673 回答