AppSync BatchGet Filtered Возвращает ошибку предела - PullRequest
0 голосов
/ 04 октября 2018

Фон

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

Любая помощь будет принята с благодарностью!

1 Ответ

0 голосов
/ 05 октября 2018

Это ожидаемое поведение.В случае с DynamoDb выражение фильтра применяется после завершения запроса, но до возвращения результатов.Таким образом, возможно, ваш запрос возвратил результаты, которые не были релевантны с точки зрения выражения фильтра и впоследствии были отфильтрованы, и вы получите следующие токены для получения большего количества результатов.После нескольких следующих токенов вы получаете релевантные результаты, которые вы можете отобразить пользователю.

С точки зрения DynamoDb, одна операция сканирования будет считывать до максимального количества установленных элементов (если используется параметр limit, который в вашем случае установлен на 3) или до 1 МБ данных, а затемприменить любую фильтрацию к результатам, используя FilterExpression.Когда вы устанавливаете его на 200, именно поэтому вы получаете релевантные результаты, поскольку вы, вероятно, получаете все существующие страны и применяется выражение фильтра.

...