【问题标题】:How do I implement one-to-many & many-to-many relationships in my GraphQL schema?如何在我的 GraphQL 模式中实现一对多和多对多关系?
【发布时间】:2019-12-18 03:31:00
【问题描述】:

这是我第一次使用 GraphQL,我为一个包含用户、歌曲和提示的应用程序创建了一个模式。请注意,听众和艺术家都表示为用户,并且任何用户都可以通过创建提示来“提示”歌曲

我无法正确定义架构中的一对多和多对多关系。我也很困惑如何编写突变以创建正确指向彼此的 Song/User/Tip 对象。

我知道我需要在我的架构定义中使用@connection 指令,并且我已经尝试遵循this example,但我仍然对如何将此设计转换为我的用例感到困惑。

这是我在指定对象之间的关系时所采取的尝试:

type Song @model{
  id: ID!
  title: String!
  artist: String!
  artistArray: [User]! @connection(name: "SongArtists")
  tips: [Tip]! @connection(name: "SongTips")
  totalAmountReceived: Float!
}

type Tip @model{
  id: ID!
  from: User! @connection(name: "UserTipsSent")
  to: User! @connection(name: "UserTipsReceived")
  song: Song! @connection(name: "SongTips")
  amount: Float!
  createdAt: String!
  hash: String!
}

type User @model{
  id: ID!
  name: String!
  walletAddress: String!
  totalAmountDonated: Float!
  totalAmountReceived: Float!
  songs: [Song]! @connection(name: "SongArtists")
  tipsSent: [Tip]! @connection(name: "UserTipsSent")
  tipsReceived: [Tip]! @connection(name: "UserTipsReceived")
}

我的架构没有指定任何连接

type Song @model {
  id: ID!
  title: String!
  artist: String!
  artistArray: [User]!
  tips: [Tip]!
  totalAmountReceived: Float!
}

type Tip @model {
  id: ID!
  from: User!
  to: User!
  song: Song!
  amount: Float!
  createdAt: String!
  hash: String!
}

type User @model {
  id: ID!
  name: String!
  walletAddress: String!
  totalAmountDonated: Float!
  totalAmountReceived: Float!
  songs: [Song]!
  tipsSent: [Tip]!
  tipsReceived: [Tip]!
}

我要实现以下关系

  • 提示必须与一首歌曲、“来自”用户和“至”用户相关联
  • 一首歌曲必须至少有一位艺术家(用户)
  • 一个用户可能有很多歌曲
  • 用户可能已发送和/或收到许多提示

我也不知道如何编写一个突变(例如)创建一首歌曲(指向正确的艺术家/用户),同时确保艺术家(用户对象中的歌曲数组)引用我刚刚创作的歌曲。

值得注意的是,我在 AWS AppySync DynamoDB 中创建了 3 个表(歌曲、用户、提示),并且希望能够检索(例如)用户、他们制作的所有歌曲,以及他们在一次查询中收到的所有提示。

【问题讨论】:

    标签: graphql aws-appsync


    【解决方案1】:

    我目前的解决方案:

    GraphQL 本身还不支持多对多关系。我简化了我的模式(不理想,但暂时让它工作)以放弃 M2M 关系并在我的连接中添加了一个 keyField。示例:

    type Song @model {
      id: ID!
      title: String!
      artist: String!
      artistObject: User! @connection(name: "ArtistSong", keyField: "userId")
      tips: [Tip]! @connection(name: "SongTip", sortField: "createdAt")
      totalAmountReceived: Float!
      inRotation: Boolean!
    }
    
    type User @model {
      id: ID!
      name: String!
      walletAddress: String!
      totalAmountDonated: Float!
      totalAmountReceived: Float!
      songs: [Song]! @connection(name: "ArtistSong", keyField: "userId")
      tipsSent: [Tip]! @connection(name: "FromUserTip")
      tipsReceived: [Tip]! @connection(name: "ToUserTip")
      email: String
    }
    

    现在,一首歌曲必须只有一位艺术家(用户)。我还没有实现提示的连接,但它适用于用户和歌曲。

    我通过在我的突变中使用名为songArtistObjectId 的字段创建了链接到它们各自用户对象的歌曲(参考我的歌曲模型上的artistObject 字段)。

    这是我使用的突变(假设用户/艺术家已经创建并且您有他们的 ID):

    mutation CreateSong {
      createSong(input: { 
        title: "Ghost", 
        artist: "quickly, quickly",
        songArtistObjectId: "e412ca8a-367c-4cda-bc6f-91aa2d85c180",
        totalAmountReceived: 0,
        inRotation: true
      }) {
        id
        title
        artist
        artistObject {
          id
          name
          walletAddress
        }
      }
    }
    

    如果您还使用 AWS Amplify/AppSync,在本地更新架构后,请务必通过 Amplify CLI 将更改推送到云端:

    amplify api gql-compile
    amplify push
    

    希望这会有所帮助!如果您有任何其他问题,请告诉我(:

    【讨论】:

    • 在创作歌曲的同时,如何添加Tips?这就是我真正需要知道的。你有一个属性 songTipIds 并传入一个 ID 数组吗?它是如何工作的?
    猜你喜欢
    • 2019-08-04
    • 2011-11-09
    • 2018-09-28
    • 2015-02-06
    • 2018-10-14
    • 2012-04-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多