查询相关表的PK的多对多关系即按相关表列过滤

问题描述

我在notetag这两个表之间有一个多对多关系,并且希望能够通过它们的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
            }
          }
        }
      }
    }
  }
}