我们正在使用带有附加DynamoDB数据源的AWS AppSync。在将批处理结果返回给客户之前尝试过滤查询时,我们遇到了一个非常困惑的情况。目的是根据要过滤的键中包含的子字符串来过滤结果。
我们的DynamoDB具有一个如下所示的组合键:
nameGroup: String // partition key; the first letter of the sort key value
name: String // sort key; the full name of the object
Attributes:
locationID: String // a three-character string
officialName: String // a more formal name
... etc.
例如:
nameGroup: A
name: Australia
locationID: AUS
officialName: Australia
... etc.
在这里您将找到我们的请求解析器:
{
"version" : "2017-02-28",
"operation" : "Query",
"index" : "nameGroup-locationID-index",
"query" : {
## Query based off of first letter of supplied String **
"expression" : "nameGroup = :nameGroup",
"expressionValues" : {
":nameGroup" : $util.dynamodb.toDynamoDBJson(${ctx.args.filter.substring(0,1)})
}
},
"filter" : {
## Filter query list with 'contains' expression **
"expression" : "contains(#name, :name)",
"expressionNames" : {
"#name" : "name"
},
"expressionValues" : {
":name" : $util.dynamodb.toDynamoDBJson(${ctx.args.filter})
}
},
## Add 'limit' and 'nextToken' arguments to implement pagination **
"limit": $util.defaultIfNull(${ctx.args.count}, 3),
"nextToken": $util.toJson($util.defaultIfNullOrBlank(${ctx.args.nextToken}, null))
}
还有我们的响应解析器:
{
## Change default return field (items) to appropriate PaginatedCountries field **
"countryRefs": $util.toJson($ctx.result.items),
"nextToken": $util.toJson($util.defaultIfNullOrBlank($context.result.nextToken, null))
}
当我们用类似这样的查询时:
getCountryList(filter: $filter) {
countryRefs {
name
locationID
officialName
}
nextToken
}
其中filter
变量的值随着用户输入字符而变化-例如,$filter = A
,然后是$filter = Au
,然后是$filter = Aus
等,我们得到非常奇怪的回报。在几乎所有情况下,我们似乎都会得到以下信息:
{
"data": {
"getCountryList": {
"countryRefs": [],
"nextToken": "eyJ2ZXJzaW9uIjoxLCJ0b2..." // a very long string token
}
}
}
奇怪的是,如果使用nextToken
,我们将在结果的第二页或第三页中找到所需的结果:
{
"data": {
"getCountryList": {
"countryRefs": [
{
"locationID": "AUS",
"name": "Australia"
},
{
"locationID": "AUT",
"name": "Austria"
}
],
"nextToken": "eyJ2ZXJzaW9uIjoxLCJ0b2..." // another very long string token
}
}
}
我们花了太多时间认为这是我们的过滤器表达式存在的问题(例如contains
是问题还是begins_with
是问题?)。不过,我们注意到,如果我们将limit
(默认的3
或通过客户提供的count
)更改为通常大于<< / em> em>在查询中将返回的元素数组的预期大小,即在将过滤器表达式应用于结果之前,该问题似乎不存在。
例如,使用filter: 'Au'
,如果我们将默认限制设置为200
而不是3
,我们得到的正是我们应该得到的(只有两个国家/地区名称以'Au')!
我的问题是:为什么limit
显然返回我要调用的具有“隐藏”值的数组?我的猜测是,除了发现过滤器匹配的索引外,返回的总返回值带有一堆空值。无论哪种方式,为什么我们都不能以预期的方式获得回报?为什么limit
在这里过滤的不仅是收益的数量,即收益的实际构造方式?
任何帮助将不胜感激!
答案 0 :(得分:0)
这是预期的行为。发生的情况是,对于DynamoDb,在查询完成后但返回结果之前将应用过滤器表达式。因此,从根本上讲,您的查询可能返回的结果与过滤器表达式角度无关,随后被过滤掉,您将获得下一个标记以检索更多结果。跟随几个下一个标记之后,您检索可以显示给用户的相关结果。
从DynamoDb角度来看,一次“扫描”操作将最多读取设置的最大项目数(如果使用您的情况下设置为3的limit参数)或最多1 MB的数据,然后应用任何过滤使用FilterExpression获取结果。当您将其设置为200时,这就是为什么您会获得相关结果的原因,因为您可能会获得所有现有的国家/地区并且应用了过滤器表达式。