如何处理 aws-appsync 中的关系?

How to work with relationships in aws-appsync?

我是 aws 和 graphql 的新手。我正在研究 appsync 并尝试在两种类型之间建立关系。以下是我的架构:

type BadCustomer {
    id: ID!
    name: String!
    phone: AWSPhone
    email: AWSEmail
    streetAddress: String
    dob: AWSDate
    passportNumber: String
    driversLicenceNumber: String
    ipAddress: AWSIPAddress
}

type BadCustomerConnection {
    items: [BadCustomer]
    nextToken: String
}

input CreateBadCustomerInput {
    name: String!
    phone: AWSPhone
    email: AWSEmail
    streetAddress: String
    dob: AWSDate
    passportNumber: String
    driversLicenceNumber: String
    ipAddress: AWSIPAddress
}

input CreateDamageInput {
    damage: Float!
    comment: String
}

input CreateIndustryInput {
    name: String!
}

input CreateSubscriberInput {
    name: String!
    email: AWSEmail!
    phone: AWSPhone
    streetAddress: String!
    subscriberIndustryId: ID!
}

type Damage {
    id: ID!
    customer: BadCustomer!
    industry: Industry!
    victim: Subscriber!
    damage: Float!
    comment: String
}

type DamageConnection {
    items: [Damage]
    nextToken: String
}

input DeleteBadCustomerInput {
    id: ID!
}

input DeleteDamageInput {
    id: ID!
}

input DeleteIndustryInput {
    id: ID!
}

input DeleteSubscriberInput {
    id: ID!
}

type Industry {
    id: ID!
    name: String!
    subscribers(
        filter: TableSubscriberFilterInput,
        sortDirection: ModelSortDirection,
        limit: Int,
        nextToken: String
    ): SubscriberConnection
}

type IndustryConnection {
    items: [Industry]
    nextToken: String
}

enum ModelSortDirection {
    ASC
    DESC
}

type Mutation {
    createIndustry(input: CreateIndustryInput!): Industry
    updateIndustry(input: UpdateIndustryInput!): Industry
    deleteIndustry(input: DeleteIndustryInput!): Industry
    createSubscriber(input: CreateSubscriberInput!): Subscriber
    updateSubscriber(input: UpdateSubscriberInput!): Subscriber
    deleteSubscriber(input: DeleteSubscriberInput!): Subscriber
    createBadCustomer(input: CreateBadCustomerInput!): BadCustomer
    updateBadCustomer(input: UpdateBadCustomerInput!): BadCustomer
    deleteBadCustomer(input: DeleteBadCustomerInput!): BadCustomer
    createDamage(input: CreateDamageInput!): Damage
    updateDamage(input: UpdateDamageInput!): Damage
    deleteDamage(input: DeleteDamageInput!): Damage
}

type Query {
    getIndustry(id: ID!): Industry
    listIndustries(filter: TableIndustryFilterInput, limit: Int, nextToken: String): IndustryConnection
    getSubscriber(id: ID!): Subscriber
    listSubscribers(filter: TableSubscriberFilterInput, limit: Int, nextToken: String): SubscriberConnection
    getBadCustomer(id: ID!): BadCustomer
    listBadCustomers(filter: TableBadCustomerFilterInput, limit: Int, nextToken: String): BadCustomerConnection
    getDamage(id: ID!): Damage
    listDamages(filter: TableDamageFilterInput, limit: Int, nextToken: String): DamageConnection
}

type Subscriber {
    id: ID!
    name: String!
    email: AWSEmail!
    phone: AWSPhone
    streetAddress: String!
    industry: Industry!
}

type SubscriberConnection {
    items: [Subscriber]
    nextToken: String
}

type Subscription {
    onCreateIndustry(id: ID, name: String): Industry
        @aws_subscribe(mutations: ["createIndustry"])
    onUpdateIndustry(id: ID, name: String): Industry
        @aws_subscribe(mutations: ["updateIndustry"])
    onDeleteIndustry(id: ID, name: String): Industry
        @aws_subscribe(mutations: ["deleteIndustry"])
    onCreateSubscriber(
        id: ID,
        name: String,
        email: AWSEmail,
        phone: AWSPhone,
        streetAddress: String
    ): Subscriber
        @aws_subscribe(mutations: ["createSubscriber"])
    onUpdateSubscriber(
        id: ID,
        name: String,
        email: AWSEmail,
        phone: AWSPhone,
        streetAddress: String
    ): Subscriber
        @aws_subscribe(mutations: ["updateSubscriber"])
    onDeleteSubscriber(
        id: ID,
        name: String,
        email: AWSEmail,
        phone: AWSPhone,
        streetAddress: String
    ): Subscriber
        @aws_subscribe(mutations: ["deleteSubscriber"])
    onCreateBadCustomer(
        id: ID,
        name: String,
        phone: AWSPhone,
        email: AWSEmail,
        streetAddress: String
    ): BadCustomer
        @aws_subscribe(mutations: ["createBadCustomer"])
    onUpdateBadCustomer(
        id: ID,
        name: String,
        phone: AWSPhone,
        email: AWSEmail,
        streetAddress: String
    ): BadCustomer
        @aws_subscribe(mutations: ["updateBadCustomer"])
    onDeleteBadCustomer(
        id: ID,
        name: String,
        phone: AWSPhone,
        email: AWSEmail,
        streetAddress: String
    ): BadCustomer
        @aws_subscribe(mutations: ["deleteBadCustomer"])
    onCreateDamage(id: ID, damage: Float, comment: String): Damage
        @aws_subscribe(mutations: ["createDamage"])
    onUpdateDamage(id: ID, damage: Float, comment: String): Damage
        @aws_subscribe(mutations: ["updateDamage"])
    onDeleteDamage(id: ID, damage: Float, comment: String): Damage
        @aws_subscribe(mutations: ["deleteDamage"])
}

input TableBadCustomerFilterInput {
    id: TableIDFilterInput
    name: TableStringFilterInput
    phone: TableStringFilterInput
    email: TableStringFilterInput
    streetAddress: TableStringFilterInput
    dob: TableStringFilterInput
    passportNumber: TableStringFilterInput
    driversLicenceNumber: TableStringFilterInput
    ipAddress: TableStringFilterInput
}

input TableBooleanFilterInput {
    ne: Boolean
    eq: Boolean
}

input TableDamageFilterInput {
    id: TableIDFilterInput
    damage: TableFloatFilterInput
    comment: TableStringFilterInput
}

input TableEventFilterInput {
    id: TableIDFilterInput
    name: TableStringFilterInput
    where: TableStringFilterInput
    when: TableStringFilterInput
    description: TableStringFilterInput
}

input TableFloatFilterInput {
    ne: Float
    eq: Float
    le: Float
    lt: Float
    ge: Float
    gt: Float
    contains: Float
    notContains: Float
    between: [Float]
}

input TableIDFilterInput {
    ne: ID
    eq: ID
    le: ID
    lt: ID
    ge: ID
    gt: ID
    contains: ID
    notContains: ID
    between: [ID]
    beginsWith: ID
}

input TableIndustryFilterInput {
    id: TableIDFilterInput
    name: TableStringFilterInput
}

input TableIntFilterInput {
    ne: Int
    eq: Int
    le: Int
    lt: Int
    ge: Int
    gt: Int
    contains: Int
    notContains: Int
    between: [Int]
}

input TableStringFilterInput {
    ne: String
    eq: String
    le: String
    lt: String
    ge: String
    gt: String
    contains: String
    notContains: String
    between: [String]
    beginsWith: String
}

input TableSubscriberFilterInput {
    id: TableIDFilterInput
    name: TableStringFilterInput
    email: TableStringFilterInput
    phone: TableStringFilterInput
    streetAddress: TableStringFilterInput
}

input UpdateBadCustomerInput {
    id: ID!
    name: String
    phone: AWSPhone
    email: AWSEmail
    streetAddress: String
    dob: AWSDate
    passportNumber: String
    driversLicenceNumber: String
    ipAddress: AWSIPAddress
}

input UpdateDamageInput {
    id: ID!
    damage: Float
    comment: String
}

input UpdateIndustryInput {
    id: ID!
    name: String
}

input UpdateSubscriberInput {
    id: ID!
    name: String
    email: AWSEmail
    phone: AWSPhone
    streetAddress: String
    subscriberIndustryId: ID
}

schema {
    query: Query
    mutation: Mutation
    subscription: Subscription
}

我想在 SubscribersIndustry 之间建立关系。每个订户属于一个行业。我为 Subscriber.industryIndustry.subscribers 设置了解析器。

Subscriber.industry解析器,数据源Industrytable:

{
    "version": "2017-02-28",
    "operation": "GetItem",
    "key": {
        "id": $util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.source.subscriberIndustryId, "___xamznone____"))
    }
}

Industry.subscribers解析器,数据源Subscribertable:

#set( $limit = $util.defaultIfNull($context.args.limit, 10) )
{
  "version": "2017-02-28",
  "operation": "Query",
  "query": {
      "expression": "#connectionAttribute = :connectionAttribute",
      "expressionNames": {
          "#connectionAttribute": "id"
    },
      "expressionValues": {
          ":connectionAttribute": {
              "S": "$context.source.id"
      }
    }
  },
  "scanIndexForward":   #if( $context.args.sortDirection )
    #if( $context.args.sortDirection == "ASC" )
true
    #else
false
    #end
  #else
true
  #end,
  "filter":   #if( $context.args.filter )
$util.transform.toDynamoDBFilterExpression($ctx.args.filter)
  #else
null
  #end,
  "limit": $limit,
  "nextToken":   #if( $context.args.nextToken )
"$context.args.nextToken"
  #else
null
  #end
}

我有以下疑问:

query ListIndustries {
  listIndustries {
    items {
      id
      name
     subscribers {
      items {
        id
        name
        streetAddress
      }
    }

    }
  }
}


query ListSubscribers {
  listSubscribers{
    items {
      id
      name
      industry {
        name
      }
    }
  }
}

如果我 运行 ListSubscribers 在 appsync 控制台上查询,它会给我想要的结果,例如:

{
  "data": {
    "listSubscribers": {
      "items": [
        {
          "id": "d04d6ef4-95bf-4b01-9a6a-13f550dbfa8f",
          "name": "John Doe",
          "industry": {
            "name": "Real Estate"
          }
        },
        {
          "id": "96fa3e60-fdcf-4a6d-a3b6-72ec2c4701d1",
          "name": "Jane Doe",
          "industry": {
            "name": "Ecommerce"
          }
        },
        {
          "id": "413dd506-afd4-474e-a850-54a39eb1eeeb",
          "name": "John Doe",
          "industry": {
            "name": "Real Estate"
          }
        }
      ]
    }
  }
}

但是如果我 运行 ListIndustries 查询,它不会给我该行业的订阅者列表,例如:

{
  "data": {
    "listIndustries": {
      "items": [
        {
          "id": "b904d8f3-b504-48e0-b28f-0f9ac1742186",
          "name": "Real Estate",
          "subscribers": {
            "items": []
          }
        },
        {
          "id": "167b87f2-3342-4390-80af-df53ba3c6f73",
          "name": "Ecommerce",
          "subscribers": {
            "items": []
          }
        }
      ]
    }
  }
}

需要有人帮我解决这个问题。

我在 Industry.subscribers 解析器中错过了 index。添加它解决了问题。

我需要更多信息才能确定,但​​看起来 Industry.subscribers 解析器可能配置错误。您的查询表达式当前指定:

"query": {
      "expression": "#connectionAttribute = :connectionAttribute",
      "expressionNames": {
          "#connectionAttribute": "id"
    },
      "expressionValues": {
          ":connectionAttribute": {
              "S": "$context.source.id"
      }
    }
  }
// There is no "index" so this is trying to query the primary index.

也就是说,"Query the primary index where the 'id' = $ctx.source.id"。根据您粘贴的对象,看起来您的订阅者对象使用 $util.autoId(),因此订阅者 'id' 永远不会等于行业 'id'。如果使用 Amplify CLI 的 @connection 指令,默认情况下将在订阅者 table 上创建一个 GSI,其哈希键名为 'subscriberIndustryId'。 Industry.subscribers 解析器应该查询 "subscriberIndustryId = $ctx.source.id" 所在的索引。如果您不使用 CLI 和 @connection,您也可以自己实现此模式。

这应该可以解决问题:

"query": {
      "expression": "#connectionAttribute = :connectionAttribute",
      "expressionNames": {
          "#connectionAttribute": "subscriberIndustryId"
    },
      "expressionValues": {
          ":connectionAttribute": {
              "S": "$context.source.id"
      }
    }
  },
"index": "gsi-IndustrySubscribers"