【问题标题】:AppSync BatchGet Filtered Returns Limit ErrorAppSync BatchGet 过滤返回限制错误
【发布时间】:2019-03-10 06:52:47
【问题描述】:

背景

我们将 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 在这里过滤的不仅仅是退货数量——即退货的实际结构方式?

任何帮助将不胜感激!

【问题讨论】:

    标签: amazon-dynamodb aws-appsync vtl


    【解决方案1】:

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

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

    【讨论】:

    • 我了解过滤器表达式如何以及何时应用于 Query,但我不了解的是如何或为什么这应该是预期的行为。如果“相关”结果——意味着任何结果——实际上存在,为什么要返回一个空的[]?为什么响应解析器不将生成的过滤查询结果压缩为一个新的值数组,该数组显示为最大限制?我想我要问的是为什么要在简单的过滤器上返回空数组,更重要的是,如何在返回客户端之前进一步压缩生成的过滤器?
    • 这取决于 DynamoDb 数据的存储方式。数据根据分区键发送到分区,排序键进一步对分区键内的数据进行排序。被调用的操作是扫描,它基于存储以唯一的方式遍历数据,遍历该分区键/排序键的数据,并在扫描一定数量的数据后检索该数据。在返回扫描的数据之前应用过滤器,您将获得一个继续令牌以检索更多结果。
    • 如果操作确实是扫描,那是有道理的;但是,我明确地执行了一个查询(请参阅上面我的请求 VTL 解析器中的“操作”字段)。那么 Query 和 Scan 在这种情况下是否有效地运行?
    • 这在 FilterExpression 的上下文中几乎相同。查看查询文档:docs.aws.amazon.com/amazondynamodb/latest/developerguide/…
    • 嗯...非常有趣。谢谢(你的)信息!关于如何获得所需结果的任何建议 - 即,我正在过滤其名称键的所有对象,其中包含一些提供的没有空数组的子字符串,并返回并调整为默认的“限制”?
    猜你喜欢
    • 2014-04-19
    • 1970-01-01
    • 1970-01-01
    • 2018-08-07
    • 2021-06-22
    • 2012-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多