如何在GraphQL模式中实现一对多和多对多关系?

时间:2019-08-10 22:41:34

标签: graphql aws-appsync

这是我第一次使用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]!
}

我想实现以下关系

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

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

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

1 个答案:

答案 0 :(得分: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
}

现在,一首歌曲必须只有一位艺术家(用户)。我尚未实现Tips的连接,但它适用于Users&Songs。

我通过使用突变体中称为songArtistObjectId的字段(引用我的Song模型上的artistObject字段)来创建链接到它们各自的User对象的Songs。

这是我使用的突变(假设已经创建了用户/艺术家,并且您具有他们的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

希望这会有所帮助!让我知道您是否还有其他疑问(: