Фон
Мы используем 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
изменяется по мере того, как пользователь вводит символы - например, $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
фильтрует здесь больше, чем просто число возвратов - т. Е. Способ, которым на самом деле структурированы возвраты?
Любая помощь будет принята с благодарностью!