Amazon dynamodb AWS AppSync查询形状响应数据(类似于SQL中的Group By)

Amazon dynamodb AWS AppSync查询形状响应数据(类似于SQL中的Group By),amazon-dynamodb,graphql,aws-appsync,Amazon Dynamodb,Graphql,Aws Appsync,我有一个DynamoDB表,其中包含了客户端所需的所有数据,但是,我希望对客户端接收的数据进行整形,以减少客户端操作 我的模式: type StateCounty { id: ID! StateName: String CountyName: String FIPSST: Int FIPSCNTY: Int Penetration: String Date: String } 要返回自定义查询,我有以下类型: type Query

我有一个DynamoDB表,其中包含了客户端所需的所有数据,但是,我希望对客户端接收的数据进行整形,以减少客户端操作

我的模式:

type StateCounty {
    id: ID!
    StateName: String
    CountyName: String
    FIPSST: Int
    FIPSCNTY: Int   
    Penetration: String
    Date: String

}
要返回自定义查询,我有以下类型:

type Query {
  getStateCountybyState(StateName: String): StateCountyConnection
}
这是可行的,只需一个简单的查询

query  getStateCountybyState {
     getStateCountybyState (StateName: "Delaware")   {
      items { 
       StateName
       CountyName
       Date    

    }
   }
  } 
结果按预期返回:

 {
      "StateName": "Delaware",
      "CountyName": "Kent",
      "Date": "02-01-2017"
    },
    {
      "StateName": "Delaware",
      "CountyName": "Sussex",
      "Date": "02-01-2016"
    },
    {
      "StateName": "Delaware",
      "CountyName": "New Castle",
      "Date": "02-01-2018"
  }
等等

我希望以以下格式返回数据:

 {
   "StateName": "Delaware" {

     { "CountyName": "Kent",
      "Date": "02-01-2017"
      },
     {
      "CountyName": "Sussex",
      "Date": "02-01-2016"
     },
     {
      "CountyName": "New Castle",
      "Date": "02-01-2018"
     }
 }
}
我已尝试将GroupCounty:[StateCountyGroup]添加到架构:

type StateCounty {
    id: ID!
    StateName: String
    CountyName: String
    FIPSST: Int
    FIPSCNTY: Int   
    Penetration: String
    Date: String
    GroupCounty: [StateCountyGroup]
}
然后在查询中引用它

query  getStateCountybyState {
     getStateCountybyState (StateName: "Delaware")   {
      items { 
       StateName
       CountyName
       Date  
       GroupCounty: [StateCountyGroup] 
    }
   }
  } 
我认为我的问题在解析器中-目前,它被配置为使用StateName作为键,但我不确定如何将StateName从主查询传递到子查询

解析程序:

{
    "version" : "2017-02-28",
    "operation" : "Query",
    "query" : {
        "expression" : "StateName = :StateName",
        "expressionValues" : {
            ":StateName" : { "S" : "${context.arguments.StateName}" },
        }
    },
    "index" : "StateName-index-copy",
    "select" : "ALL_ATTRIBUTES",

}
感谢您的指导-我已经查阅了文档好几次,但找不到示例

更新

我尝试了Richard的以下建议——这肯定是正确的,但是,尽管主题有多种变化,我要么返回null,要么返回以下错误(为了简洁起见,我删除了错误中返回的一些county对象):


通过阅读上面的内容,您的原始查询似乎返回了您想要的正确结果,但不是您想要的响应格式,因为您希望“StateName”是顶级JSON键,其值是作为参数传入的状态的JSON对象。准确吗?如果是这样的话,为什么不使用已经可以使用的相同查询,但使用不同的响应模板呢。比如:

#set($myresponse = {
  "$ctx.args.StateName": $ctx.result.items
})    
$util.toJson($myresponse)
请注意,
$myresponse
与您上面的示例“stateName”不完全相同:“特拉华”{…}不是完全有效的JSON,因此我不想假设什么是好的结构,但关键仍然是,如果您已经从查询中获得了正确的结果,我将尝试更改GraphQL结果的结构

现在,如果我误读了上面的内容,并且您没有从查询中获得正确的结果,那么我可以通过另一种方式阅读您的“主查询到子查询”语句,即您试图对查询结果应用附加的
“过滤器”
。如果是这种情况,那么您需要这样的东西:

{
    "version" : "2017-02-28",
    "operation" : "Query",
    "query" : {
        "expression" : "StateName = :StateName",
        "expressionValues" : {
            ":StateName" : { "S" : "${context.arguments.StateName}" },
        }
    },
    "index" : "StateName-index-copy",
    "select" : "ALL_ATTRIBUTES",
    "filter" : {
      "expression" : "#population >= :population",
      "expressionNames" : {
        "#population" : "population"
      },
      "expressionValues" : {
        ":population" : $util.dynamodb.toDynamoDBJson($ctx.args.population)
      }
    }
}
type State {
    id: ID!
    population: String!
    governor: String!
}

type Query {
    allStates: [State]
}
query {
  allStates{
    id
    population
  }
}
query {
  allStates(StateName:"Texas"){
    StateName
  }
}
我在这里举了一个例子,您的查询可能还需要根据每个县的人口规模进行过滤。这可能不能代表你想要的东西,但希望能有所帮助

编辑更多信息2018年4月16日

我已经以一步一步的方式写了更多关于这一点的信息,以分门别类地介绍这些概念

这里的关键不仅是响应模板,还包括请求返回的字段(因为这是GraphQL的本质)。让我们举个例子来介绍一下。现在使用GraphQL返回单个项(因为响应模板正在将数组转换为单个项),因此需要更改预期的GraphQL查询响应类型。假设您的模式中有一个GraphQL类型,如下所示:

{
    "version" : "2017-02-28",
    "operation" : "Query",
    "query" : {
        "expression" : "StateName = :StateName",
        "expressionValues" : {
            ":StateName" : { "S" : "${context.arguments.StateName}" },
        }
    },
    "index" : "StateName-index-copy",
    "select" : "ALL_ATTRIBUTES",
    "filter" : {
      "expression" : "#population >= :population",
      "expressionNames" : {
        "#population" : "population"
      },
      "expressionValues" : {
        ":population" : $util.dynamodb.toDynamoDBJson($ctx.args.population)
      }
    }
}
type State {
    id: ID!
    population: String!
    governor: String!
}

type Query {
    allStates: [State]
}
query {
  allStates{
    id
    population
  }
}
query {
  allStates(StateName:"Texas"){
    StateName
  }
}
如果您只是如上所述转换模板中的响应,那么如果您运行以下操作,您将看到类似“类型不匹配错误,预期类型列表”的错误:

{
    "version" : "2017-02-28",
    "operation" : "Query",
    "query" : {
        "expression" : "StateName = :StateName",
        "expressionValues" : {
            ":StateName" : { "S" : "${context.arguments.StateName}" },
        }
    },
    "index" : "StateName-index-copy",
    "select" : "ALL_ATTRIBUTES",
    "filter" : {
      "expression" : "#population >= :population",
      "expressionNames" : {
        "#population" : "population"
      },
      "expressionValues" : {
        ":population" : $util.dynamodb.toDynamoDBJson($ctx.args.population)
      }
    }
}
type State {
    id: ID!
    population: String!
    governor: String!
}

type Query {
    allStates: [State]
}
query {
  allStates{
    id
    population
  }
}
query {
  allStates(StateName:"Texas"){
    StateName
  }
}
这是因为您的回复不再返回单个项目。相反,您需要更改GraphQL响应类型
[State]
,以匹配模板转换正在执行的操作
State
,如下所示:

type State {
    StateName: String
}

type Query {
    allStates: State
}
现在,如果您的解析器请求模板正在执行返回项目列表的操作(如DynamoDB扫描或查询),您可以将列表转换为响应模板中的单个项目,如下所示:

#set($convert = {"StateName" : $ctx.result.items })
$util.toJson($convert)
然后运行以下GraphQL查询:

query {
  allStates{
    StateName
  }
}
您将得到一个包含结果数组的单个对象:

{
  "data": {
    "allStates": {
      "StateName": "[{id=1, population=10000, governor=John Smith}]"
    }
  }
}
然而,虽然这可能指出了您的错误,但这返回了一个
StateName
,从您最初的问题来看,我认为您希望通过将响应中的记录结合起来进行一些优化,以及一些潜在的筛选,来做得更多。一种方法是创建一个数组(或者您可以创建一个映射{}),并根据一些条件填充它。例如,修改查询以将
StateName
作为参数:

type Query {
    allStates(StateName: String!): Post
}
然后,您可以在解析器响应模板中对此进行筛选,方法是使用
#foreach
#if()
条件,然后仅当响应中的项用于您请求的状态时才调用
.add()

#set($convert = {"StateName" : [] })
#foreach($item in $ctx.result.items)
  #if($item["StateName"]=="$ctx.args.StateName")
    $util.qr($convert.get("StateName").add("$item"))
  #end
#end
$util.toJson($convert)
因此,现在您可以运行类似以下内容:

{
    "version" : "2017-02-28",
    "operation" : "Query",
    "query" : {
        "expression" : "StateName = :StateName",
        "expressionValues" : {
            ":StateName" : { "S" : "${context.arguments.StateName}" },
        }
    },
    "index" : "StateName-index-copy",
    "select" : "ALL_ATTRIBUTES",
    "filter" : {
      "expression" : "#population >= :population",
      "expressionNames" : {
        "#population" : "population"
      },
      "expressionValues" : {
        ":population" : $util.dynamodb.toDynamoDBJson($ctx.args.population)
      }
    }
}
type State {
    id: ID!
    population: String!
    governor: String!
}

type Query {
    allStates: [State]
}
query {
  allStates{
    id
    population
  }
}
query {
  allStates(StateName:"Texas"){
    StateName
  }
}
这将返回作为参数传递的特定状态的结果。但是您会注意到查询的选择集是
StateName
。通过在GraphQL类型中列出可能的状态,您可以引入更多的灵活性:

type State {
    StateName: String
    Seattle: String
    Texas: String
}
现在,您可以更改解析器响应模板以使用参数来构建返回数组,因为它可以在选择集中指定此参数:

#set($convert = {"$ctx.args.StateName" : [] })
#foreach($item in $ctx.result.items)
  #if($item["StateName"]=="$ctx.args.StateName")
    $util.qr($convert.get("$ctx.args.StateName").add("$item"))
  #end
#end
$util.toJson($convert)
因此,我可以运行此查询:

query {
  allPosts(StateName:"Seattle"){
    Seattle
  }
}
我得到了我的结果。请注意,虽然将
西雅图
作为参数传递,但请求返回
德克萨斯州

query {
  allPosts(StateName:"Seattle"){
    Texas
  }
}
这将不起作用,因为您在地图中创建的响应对象是
西雅图:[……]
,但选择集是
德克萨斯州


您可能要做的最后一件事是返回多个状态,这可以通过构建一个由状态名称键入的巨型映射来实现,也可以通过向返回类型添加状态名称(如上所示)使用参数或选择集来实现。这取决于你,所以我不确定你会想要什么,但希望这能证明你可以操纵响应以满足你的需求。

非常感谢@Richard为我指明了正确的方向,这是明智的