PostgreSQL:全文搜索多租户网站,加上网站的部分内容

时间:2013-07-13 14:35:48

标签: postgresql full-text-search categories faceted-search

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

1)仅搜索他们当前访问的网站(但不是所有网站),以及
2)仅搜索该网站的一部分(例如,限制搜索到该网站上的博客或论坛),以及
3)仅搜索单个论坛帖子。

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

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

我可以想到三种方法:

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

  2. 创建一个单一索引,并插入[要索引的文本]魔术词,如:  “的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';
    
  4. 上述三种方法中的任何一种都有意义吗?还有更好的选择吗?


    (细节:但是,也许方法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,然后使用一个索引检查全文搜索列。) )
    / End details。


    更新,一周后:我正在使用ElasticSearch。我得到的印象是,对于带有关系数据库/ PostgreSQL的分面搜索,不存在可扩展的解决方案。与ElasticSearch集成似乎与实现和测试以及调整此处建议的方法一样简单。 (例如,PostgreSQL的词干分析器/无论它叫什么,可能会将“section_NNN”分成两个词:“section”和“NNN”,从而在页面上不存在索引词!解决这些小烦恼问题的棘手问题。)

2 个答案:

答案 0 :(得分:1)

通常的做法是创建:

  • 一个全文索引:

    CREATE INDEX idx1    ON dw1_posts使用杜松子酒(to_tsvector('english',approved_text));

  • site_id上​​的一个简单索引:

    CREATE INDEX idx2   在dw1_posts(page_id);

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

    CREATE INDEX idx3   在dw1_posts(site_id);

然后,SQL计划员的业务决定使用哪些,以及依赖于查询和列中值的分布的顺序。在你真正目睹慢查询之前,试图超越计划者毫无意义。

答案 1 :(得分:0)

另一种替代方案,类似于“site_&lt; site-id&gt;”和“section_&lt; section-id&gt;”和“page_&lt; page-id&gt;”替代方案,应该是将文本添加到 index 的前缀:

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

然后在搜索时使用prefix matching (i.e. :*)

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

其中NN是网站ID,MMM是部门ID。

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