问题描述
我在note
和tag
这两个表之间有一个多对多关系,并且希望能够通过它们的tagId
搜索所有笔记。由于很多原因,我有一个联结表note_tag
。
我的目标是在Postgraphile生成的Graphql模式上公开一个可查询的计算字段,以及note
表的其他属性。
我正在玩postgraphile-plugin-connection-filter
。这个插件可以通过authorId之类的东西(可能是1:many)进行过滤,但是我无法弄清楚如何通过many:many进行过滤。我的笔记表上有一个名为tags
的计算列,它是JSON。有没有一种方法可以“查看”此json并找出id = 1的位置?
这是我的计算列tags
:
create or replace function note_tags(note note,tagid text)
returns jsonb as $$
select
json_strip_nulls(
json_agg(
json_build_object(
'title',tag.title,'id',tag.id,)
)
)::jsonb
from note
inner join note_tag on note_tag.tag_id = tagid and note_tag.note_id = note.id
left join note_tag nt on note.id = nt.note_id
left join tag on nt.tag_id = tag.id
where note.account_id = '1'
group by note.id,note.title;
$$ language sql stable;
据我了解上面的函数,我基于给(给函数)的tagid返回inner join note_tag on note_tag.tag_id = tagid
的jsonb。那么,为什么在计算列时json不被id
过滤?
我正在尝试这样查询:
query notesByTagId {
notes {
edges {
node {
title
id
tags(tagid: "1")
}
}
}
}
但是现在当我执行此查询时,我在tags
字段中返回了字符串化的JSON。但是,无论注释实际上是否属于该标签,所有标签都包含在json中。
例如,此id = 1的注释应仅包含id = 1和id = 2的标签。现在,它将返回数据库中的每个标签
{
"data": {
"notes": {
"edges": [
{
"node": {
"id": "1","tags": "[{\"id\":\"1\",\"title\":\"Psychology\"},{\"id\":\"2\",\"title\":\"Logic\"},{\"id\":\"3\",\"title\":\"Charisma\"}]",...
此计算列的关键因素在于,即使我们在单个tagid
上搜索笔记,JSON也必须包含笔记所属的所有标签
这是我的简化表格...
注意:
create table notes(
id text,title text
)
标签:
create table tag(
id text,title text
)
note_tag:
create table note_tag(
note_id text FK references note.id
tag_id text FK references tag.id
)
更新
create or replace function note_tags(n note)
returns setof tag as $$
select tag.*
from tag
inner join note_tag on (note_tag.tag_id = tag.id)
where note_tag.note_id = n.id;
$$ language sql stable;
我能够在填充了tags
字段的情况下检索所有注释,但是现在我需要能够过滤出不属于特定标签的注释,同时仍然保留所有属于给定的音符。
所以问题仍然与上面相同:我们如何根据相关表的PK过滤表?
解决方法
经过一段时间的挖掘,我认为我遇到了一个很好的方法。基于this response,我制作了一个函数,该函数返回给定notes
的所有tagid
。
这里是:
create or replace function all_notes_with_tag_id(tagid text)
returns setof note as $$
select distinct note.*
from tag
inner join note_tag on (note_tag.tag_id = tag.id)
inner join note on (note_tag.note_id = note.id)
where tag.id = tagid;
$$ language sql stable;
方法中的错误是期望计算列完成所有工作,而其唯一的工作应该是获取所有数据。现在可以像下面这样直接在graphql中调用此函数all_nuggets_with_bucket_id
:
query MyQuery($tagid: String!) {
allNotesWithTagId(tagid: $tagid) {
edges {
node {
id
title
tags {
edges {
node {
id
title
}
}
}
}
}
}
}