2

任务:在 PostgreSQL 中的多个表中实现全文搜索。

比如一个项目表——projects:有两个字段需要搜索:title和description。在这个表上创建一个索引:

ALTER TABLE public.projects ADD COLUMN search_fts tsvector;
UPDATE public.projects SET search_fts =
to_tsvector(
    coalesce(title, '') ||' '||
    coalesce(description, '') || ' '
);
CREATE INDEX in_projects_idx ON public.projects
  USING gin (search_fts);

现在搜索很简单:

SELECT
    DISTINCT p.id,
    p.title,
    ts_rank(
        p.search_fts,
        to_tsquery('word1 | word2')
    ) as rank
FROM
    projects p
WHERE
    p.search_fts @@ to_tsquery('word1 | word2')
ORDER BY rank DESC;

精致。现在我们需要查看表和项目类别——project_categories。类似于创建 tsvector 和为表上的字段名。现在的搜索查询是:

SELECT
    DISTINCT p.id,
    p.title,
    category.name as categoryName,
    ts_rank(
        (
            coalesce(p.search_fts, '') ||' '||
            coalesce(category.search_fts, '')
        ),
        to_tsquery('word1 | word2 | categoryName')
    ) as rank
FROM
    projects p
LEFT JOIN project_categories category
    ON p.category_id = category.category_id
WHERE
    (
        coalesce(p.search_fts, '') ||' '||
        coalesce(category.search_fts, '')
    ) @@ to_tsquery('word1 | word2 | categoryName')
ORDER BY rank DESC;

更精致。现在搜索必须以一对多和多对多的形式在几十个与项目相关的表上工作。

加入人数越来越多。结合到越来越多的领域。

实际上这个问题是我要去的正确方式吗?你将如何解决这个问题?

我也考虑了有视图的版本。例如,基于这样的请求:

(
  SELECT 
      p.id as project_id,
      p.search_fts
  FROM projects p
) UNION ALL (
  SELECT 
      p.id as project_id,
      category.search_fts
  FROM projects p
  JOIN project_categories category
      ON p.category_id = category.category_id
)

最后,我们得到整体指数。通过哪个搜索。但在视图中必须结合十几个不同通信选项的请求。对您对此选项的看法感兴趣。

对不起我的英语不好。

4

1 回答 1

3

你有几个选择:

  • 在所有输入表上使用触发器来维护一个汇总表,该汇总表将所有感兴趣的记录组合到文本行中。这适用于简单的情况,例如customer具有 1个或多个条目phone和一个或多个address条目的 a,您可以将其放入摘要搜索表中,就像|customername|customerid|phone1|phone2|phone3|...|address1|address2|...使用简单连接和string_agg过度连接表一样。但是,它对深度嵌套关系的扩展性很差,并且可能会带来一些锁定和并发问题。

  • 使用旨在解决复杂搜索问题的外部搜索系统,例如 Apache Solr。

于 2013-02-24T23:51:24.710 回答