0

背景

我们将 AWS AppSync 与附加的 DynamoDB 数据源一起使用。在将批处理结果返回给我们的客户之前尝试过滤查询时,我们遇到了一个非常令人困惑的情况。目标是根据被过滤的键中包含的子字符串过滤我们的结果。

我们的 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用户输入字符时,var 的值会发生变化——例如,,$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)更改为通常大于查询中返回的元素数组的预期大小 - 也就是说,之前过滤器表达式应用于结果 - 问题似乎不存在。

例如,使用filter: 'Au',如果我们将默认限制设置为200而不是3,我们得到的正是我们应该得到的(只有两个以 'Au' 开头的国家名称)!

我的问题是:为什么limit显然返回了我将要调用的具有“隐藏”值的数组?我的猜测是,除了找到过滤器匹配的索引之外,返回的总返回大小带有一堆空值。无论哪种方式,为什么我们没有以预期的方式获得回报?为什么在limit这里过滤的不仅仅是回报的数量——即回报的实际结构方式?

任何帮助将不胜感激!

4

1 回答 1

0

这是预期的行为。发生的情况是,使用 DynamoDb,在 Query 完成之后但在返回结果之前应用过滤器表达式。所以基本上它可能是您的查询返回的结果与过滤器表达式的角度不相关,随后被过滤掉,您获得下一个令牌以检索更多结果。在遵循几个下一个标记之后,您可以检索可以显示给用户的相关结果。

从 DynamoDb 的角度来看,单个 Scan 操作将读取最多设置的最大项目数(如果使用在您的情况下设置为 3 的限制参数)或最多 1 MB 的数据,然后对结果应用任何过滤使用过滤器表达式。当您将其设置为 200 时,这就是您获得相关结果的原因,因为您可能会获得所有现有国家并应用过滤器表达式。

于 2018-10-04T22:28:36.297 回答