1

假设我有以下伪模式,其中1-many关系是使用 Postgres 数组建模的:

CREATE TYPE quotes AS
(
  text  CHARACTER VARYING,
  is_direct CHARACTER VARYING
);

CREATE TABLE posts
(
    body  CHARACTER VARYING,
    q     quotes[]
);
insert into posts(body,q) VALUES('ninjas rock',ARRAY[ ROW('I AGREE',True)::quotes, ROW('I DISAGREE',FALSE)::quotes ]);

我的第一个问题是:如何执行选择以quote->text从整个数组中过滤掉。

这有效:

test=# select body, q[1].text from posts;
     body     |  text   
--------------+---------
 hassan rocks | I AGREE
(1 row)

但这不是(请注意,正在检索整个复合类型):

test=# select body, (q).text from posts;
     body     |                      text                       
--------------+-------------------------------------------------
 hassan rocks | {"(\"I AGREE\",true)","(\"I DISAGREE\",false)"}
(1 row)

为了解决我真正的问题,我将如何创建一个to_tsvector包含帖子正文和所有引用文本的 gin 或 gist(有或没有)索引?我不喜欢使用额外的列索引方法,因为触发器让我很伤心

目前,我的模式将帖子和引用表示为一种1-many关系,但是我认为如果 postgres 支持我正在尝试做的事情,它将大大简化事情。

4

3 回答 3

1

您可以创建一个函数来获取数组部分并以 a 的形式返回SETOF quotes并在 上调用该函数SELECT

CREATE OR REPLACE FUNCTION getquote(posts)
RETURNS SETOF quotes
LANGUAGE sql
AS $getquote$
SELECT $1.q[i].text, $1.q[i].is_direct
FROM generate_series(array_lower($1.q, 1), array_upper($1.q, 1)) AS i
$getquote$

SELECT将是:

SELECT body, (getquote(p)).* FROM posts p;

您可以创建一个视图以使事情变得更容易,您还可以对函数本身执行过滤任务。

于 2012-08-13T17:41:54.997 回答
0

我可以回答第 1 部分。

要为每个正文/引用返回一行:

SELECT body, q_unnest.text AS quote
FROM posts, UNNEST(q) AS q_unnest

要为每个帖子返回一行,其中包含一组引用文本:

SELECT posts.body, array_agg(q_unnest.text) AS quotes
FROM posts, UNNEST(q) AS q_unnest
GROUP BY posts.body

要为每个帖子返回一行,其中引用文本由分隔符分隔:

SELECT posts.body, array_to_string(array_agg(q_unnest.text), '|') AS quotes
FROM posts, UNNEST(q) AS q_unnest
GROUP BY posts.body

我设置了一个SQLFiddle,所以你可以自己尝试一下。

至于第 2 部分和索引复合类型数组,我相信它需要一个“操作员类”,根据此处的 Postgres 扩展指南。这对我来说看起来很麻烦,我还没有找到如何做到这一点的例子。

于 2014-01-30T12:40:24.183 回答
0

以下代码将“过滤”您的数组。select (unnest(q)).text from posts;. unnest将数组旋转为行。请注意,unnest它包含在括号中,这很重要,因为如果没有括号,您将无法选择特定的字段——即,unnest(q).text它是无效的,并且unnest(q)它本身会导致一行包含字符串形式的组合。

将 post txt 和 quote txt 视为单个文本单元的代码如下:

SELECT to_tsvector(q.b_txt || q.q_t) FROM
(
    SELECT b_txt,string_agg(p.q_txt,' ') as q_t 
    FROM ( SELECT 1 AS id,body b_txt, (unnest(q)).text AS q_txt FROM posts) AS p 
    GROUP BY p.id,b_txt
) AS q;

这可能需要改编成 UDF 以用于gingist索引。

于 2012-08-14T05:08:15.427 回答