Запрос DynamoDB со списком в AWS AppSync

Я пытаюсь создать запрос AWS AppSync со списком с помощью IN:

{
    "version" : "2017-02-28",
    "operation" : "Query",
    "index" : "my-index",
    "query" : {
        "expression": "id IN :ids",
        "expressionValues" : { ":ids" : $util.dynamodb.toStringSet($ctx.args.ids) }
    },
    "limit": $util.defaultIfNull(${ctx.args.first}, 20),
    "nextToken": $util.toJson($util.defaultIfNullOrBlank($ctx.args.after, null))
}

Однако, попробовав это с такими параметрами, как:

query ListItemsWithIdList {
  listItemsWithIdList(first:20, ids: ["id1", "id2"]) {
    items {
      id
    }
    nextToken
  }
}

Выдает ошибку:

Unable to parse the JSON document: 'Unexpected character ('S' (code 83)): was expecting double-quote to start field name
at [Source: (String)\"{
    \"version\" : \"2017-02-28\",
    \"operation\" : \"Query\",
    \"index\" : \"my-index\",
    \"query\" : {
        \"expression\": \"id IN :ids\",
        \"expressionValues\" : { \":ids\" : {SS=[id1, id2]} }
    },       
    \"limit\": 20,
    \"nextToken\": null
}\"; line: 7, column: 47]'"

Кажется нормальным использовать IN для оператора сравнения запросов; однако как я могу передать String List в качестве параметра и получить результаты, идентификаторы которых входят в число предоставленных параметров?

Обновлено: Исправлена ​​опечатка в имени переменной.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
0
3 942
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Я думаю, здесь может быть 2 проблемы:

  • Ваши аргументы в запросе listItemsWithIdList принимают аргумент с именем userIds. У вас есть $ctx.args.ids) в вашем шаблоне Resolver. Вам нужно использовать одно и то же имя аргумента в обоих местах.

  • Когда вы используете $util.dynamodb.toStringSet в шаблоне сопоставления, как вы видите в ошибке, он преобразуется в { \":ids\" : {SS=[id1, id2]} }. Однако вы хотите, чтобы значения id содержались в кавычках. AWS AppSync предоставляет для этой цели еще один служебный метод. Вы можете изменить свой шаблон, чтобы использовать $util.dynamodb.toStringSetJson, который затем преобразуется в { \":ids\" : {SS=[\"id1\", \"id2\"]} }.

Сообщите мне, решило ли это вашу проблему. Вот ссылка на Утилиты Resolver Mapping Template Utilities.

Спасибо, я удалил двусмысленность, вызванную userIds / ids из вопроса. Пробовал $util.dynamodb.toStringSetJson, но потом ошибка стала Invalid KeyConditionExpression: Syntax error; token: \":userIds\", near: \"IN :userIds. Думаю, IN не разрешен для запроса, этот ссылка также говорит об этом.

vahdet 25.09.2018 08:59
Ответ принят как подходящий

Я не думаю, что AWS AppSync пока поддерживает IN. Я пытаюсь протестировать ваш сценарий и придумывать решение, использующее функцию contains().

Вот результат после запроса:

Другое альтернативное решение - использовать Scan (не рекомендуется)
.

{
    "version" : "2017-02-28",
    "operation" : "Scan",
    "filter" : {
        "expression": "contains (:authors, author)",
        "expressionValues" : {
            ":authors" : $util.dynamodb.toDynamoDBJson($ctx.args.authors)
        }
    }
}

Кстати, AWS AppSync поддерживает работу BatchGetItem. Вы можете передать список ключей в одном запросе и вернуть результаты из таблицы.

## REQUEST MAPPING
#set($authors = [])
#foreach( $author in $ctx.args.authors )
    #set($map = {})
    $util.qr($map.put("author", $util.dynamodb.toString($author)))
    $util.qr($authors.add($map))
#end

{
    "version" : "2018-05-29",
    "operation" : "BatchGetItem",
    "tables" : {
        "tbDiary": {
            "keys": $util.toJson($authors),
            "consistentRead": true
        }
    }
}

## RESPONSE MAPPING
$util.toJson($ctx.result.data.tbDiary)

Спасибо за подход, но я избегаю использования раздела filter, поскольку он может испортить результаты при использовании с разбивка на страницы. Вы пробовали contains в выражение запроса, т.е. именно там, где author = :author в вашем первом фрагменте.

vahdet 25.09.2018 20:22

@vahdet Надеюсь, это пригодится!

KoingDev 26.09.2018 03:55
BatchGetItem выглядит неплохо, но я сомневаюсь в производительности. Собираюсь проверить это. Для разбивки на страницы используется другой подход, кстати: UnprocessedKeys
vahdet 26.09.2018 18:46

Надеюсь, вы уже решили это. Однако в вашей настройке есть две проблемы:

Это должно быть выражение фильтра, и, поскольку у вас нет ключевого условия, это может быть даже сканирование вместо запроса.

Затем возникают проблемы с синтаксисом (именно из-за этого на самом деле возникает ошибка): В ВЫРАЖЕНИИ добавьте круглые скобки к переменной "выражение": "идентификатор IN (: ids"),

И в EXPRESSION VALUES используйте toStringSetJson вместо toStringSet "expressionValues": {": ids": $ util.dynamodb.toStringSetJson ($ ctx.args.ids)}

Надеюсь это поможет.

Спасибо, причина, по которой я избегал Scan, заключалась в том, что его filter применяется после разбивки на страницы (см. Использование limit и nextToken в OP). Вы не можете прилично получить первым, скажем, 5 результатов, он может вернуть 3 из 10 с Scan.

vahdet 20.12.2018 13:58

Другие вопросы по теме