GraphQL解析器,用于按名称而不是ID获取项目

时间:2019-03-30 21:50:49

标签: graphql aws-appsync resolver

我有一个包含成分的DynamoDB。 AWS Appsync为我创建了一个解析器,因此我可以通过ID获取成分,但是我需要能够按名称获取成分。我已经尝试为此编写解析器,但是它不起作用。

最终,我需要编写一个解析器或API,该解析器或API可以获取字符串列表,并返回与这些字符串匹配的成分(如果存在),但这是第一步,我希望我可以创建一个它的批处理版本。

解析器:

{
    "version": "2017-02-28",
    "operation": "GetItem",
    "key": {
        "name": $util.dynamodb.toDynamoDBJson($util.transform.toDynamoDBFilterExpression($ctx.args.filter))
    }
}

响应映射模板

$util.toJson($ctx.result)

模式:

input CreateIngredientInput {
    name: String!
    vegan: Vegan
    gf: GlutenFree
}

input DeleteIngredientInput {
    id: ID!
}

enum GlutenFree {
    GLUTENFREE
    CONTAINSGLUTEN
    UNKNOWN
}

type Ingredient {
    id: ID!
    name: String!
    vegan: Vegan
    gf: GlutenFree
}

type IngredientConnection {
    items: [Ingredient]
    nextToken: String
}

input ModelBooleanFilterInput {
    ne: Boolean
    eq: Boolean
}

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

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

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

enum ModelSortDirection {
    ASC
    DESC
}

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

type Mutation {
    createIngredient(input: CreateIngredientInput!): Ingredient
    updateIngredient(input: UpdateIngredientInput!): Ingredient
    deleteIngredient(input: DeleteIngredientInput!): Ingredient
}

type Query {
    getIngredient(id: ID!): Ingredient
    getIngredientByName(name: String!): Ingredient
    listIngredients(filter: TableIngredientFilterInput, limit: Int, nextToken: String): IngredientConnection
}

type Subscription {
    onCreateIngredient(
        id: ID,
        name: String,
        vegan: Vegan,
        gf: GlutenFree
    ): Ingredient
        @aws_subscribe(mutations: ["createIngredient"])
    onUpdateIngredient(
        id: ID,
        name: String,
        vegan: Vegan,
        gf: GlutenFree
    ): Ingredient
        @aws_subscribe(mutations: ["updateIngredient"])
    onDeleteIngredient(
        id: ID,
        name: String,
        vegan: Vegan,
        gf: GlutenFree
    ): Ingredient
        @aws_subscribe(mutations: ["deleteIngredient"])
}

input TableBooleanFilterInput {
    ne: Boolean
    eq: Boolean
}

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 TableIngredientFilterInput {
    id: TableIDFilterInput
    name: TableStringFilterInput
    vegan: TableBooleanFilterInput
    gf: TableBooleanFilterInput
}

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 UpdateIngredientInput {
    id: ID!
    name: String
    vegan: Vegan
    gf: GlutenFree
}

enum Vegan {
    VEGAN
    NONVEGAN
    UNKNOWN
}

当我运行此查询时:

query getIt {
  getIngredientByName(name: "demerara") {
    id
    name
    vegan
    gf
  }
}

我得到答复:

{
  "data": {
    "getIngredientByName": null
  },
  "errors": [
    {
      "path": [
        "getIngredientByName"
      ],
      "data": null,
      "errorType": "DynamoDB:AmazonDynamoDBException",
      "errorInfo": null,
      "locations": [
        {
          "line": 2,
          "column": 3,
          "sourceName": null
        }
      ],
      "message": "The provided key element does not match the schema (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: 58EKL6IO63VL44Q1DTG9JFNJB7VV4KQNSO5AEMVJF66Q9ASUAAJG)"
    }
  ]
}

尽管demerara绝对是我数据库中的一个组成部分。

2 个答案:

答案 0 :(得分:0)

我想出了一种方法,尽管有点作弊。

当我在AppSync模式中创建资源时,会出现一个“附加索引”的下拉列表,如果我按ID进行初始索引创建,然后按第二个索引“名称”进行创建,则会使用解析器为您。就我而言

queryIngredientsByNameIndex(name: String!, first: Int, after: String): IngredientConnection

查询,其解析器为

{
  "version": "2017-02-28",
  "operation": "Query",
  "query": {
    "expression": "#name = :name",
    "expressionNames": {
      "#name": "name",
    },
    "expressionValues": {
      ":name": $util.dynamodb.toDynamoDBJson($ctx.args.name),
    },
  },
  "index": "name-index",
  "limit": $util.defaultIfNull($ctx.args.first, 20),
  "nextToken": $util.toJson($util.defaultIfNullOrEmpty($ctx.args.after, null)),
  "scanIndexForward": true,
  "select": "ALL_ATTRIBUTES",
}

答案 1 :(得分:0)

我知道这已经很老了,但是最近我遇到了一个类似的问题,可以通过向我想要搜索的架构属性添加@key指令来解决:

type User @model @key(name: "getUserByCognitoId", fields: ["cognitoId"], queryField: "getUserByCognitoId") {
  id: ID!
  cognitoId: ID!
  ...
}

文档:https://docs.amplify.aws/cli/graphql-transformer/directives#key

AppSync通过这种方式为您生成解析器并添加排序键,以使查询DynamoDB更加高效