AppSync BatchGet筛选的退货限制错误

时间:2018-10-04 19:52:17

标签: amazon-dynamodb aws-appsync vtl

背景

我们正在使用带有附加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在这里过滤的不仅是收益的数量,即收益的实际构造方式?

任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:0)

这是预期的行为。发生的情况是,对于DynamoDb,在查询完成后但返回结果之前将应用过滤器表达式。因此,从根本上讲,您的查询可能返回的结果与过滤器表达式角度无关,随后被过滤掉,您将获得下一个标记以检索更多结果。跟随几个下一个标记之后,您检索可以显示给用户的相关结果。

从DynamoDb角度来看,一次“扫描”操作将最多读取设置的最大项目数(如果使用您的情况下设置为3的limit参数)或最多1 MB的数据,然后应用任何过滤使用FilterExpression获取结果。当您将其设置为200时,这就是为什么您会获得相关结果的原因,因为您可能会获得所有现有的国家/地区并且应用了过滤器表达式。