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

Posted

技术标签:

【中文标题】GraphQL 解析器,用于按名称而不是 ID 获取项目【英文标题】:GraphQL Resolver for getting item by name, not ID 【发布时间】:2019-08-21 11:42:38 【问题描述】:

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

最终我需要编写一个解析器或 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 绝对是我数据库中的一种成分。

【问题讨论】:

你能分享你表上的键模式吗?从错误消息看来,这似乎就是它正在苦苦挣扎的地方。 不确定关键架构是什么,我的架构在上面 DynamoDB 表的关键结构。 【参考方案1】:

我知道这很旧,但我最近遇到了一个类似的问题,我可以通过向我想要搜索的架构属性添加 @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 的效率

【讨论】:

【参考方案2】:

我想出了一个办法,虽然有点作弊。

当我在 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",

【讨论】:

以上是关于GraphQL 解析器,用于按名称而不是 ID 获取项目的主要内容,如果未能解决你的问题,请参考以下文章

如何在 GraphQL 解析器中添加用于缓存的 redis 客户端

Apollo GraphQL:增强而不是覆盖默认解析器行为

用 Jest 测试 GraphQL 解析器

指定要使用的解析器 |解析器顺序

express-graphql 解析器参数在解析器中为空,但 info variableValues 填充了名称和值

Java GraphQL - 将字段值传递给对象的解析器