假设我有以下伪模式,其中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)
为了解决我真正的问题,我将如何创建一个杜松子酒或gist(带或不带to_tsvector
)索引,其中包括帖子主体和所有帖子的文本报价文字?我不希望使用索引的额外列方法作为触发器make me sad。
目前我的架构将帖子和引用表示为1-many
关系,但我认为如果postgres支持我想要做的事情,它会大大简化事情。
答案 0 :(得分:1)
您可以创建一个函数来获取数组部分并以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;
您可以创建一个视图以简化操作,还可以对函数本身执行过滤任务。
答案 1 :(得分: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以便在gin
或gist
索引中使用。
答案 2 :(得分: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扩展指南here。这对我来说似乎很麻烦,我还没有找到如何做到这一点的例子。