#amazon-dynamodb #aws-amplify #aws-appsync #aws-amplify-cli #amazon-dynamodb-index
#amazon-dynamodb #aws-amplify #aws-appsync #aws-amplify-cli #amazon-dynamodb-index
Вопрос:
Я пытаюсь запросить таблицу DynamoDB через AWS AppSync, используя AWS Android AppSync SDK и CLI Amplify. Я запрашиваю Глобальный вторичный индекс (GSI). Я получаю сообщение об ошибке:
Блок выражения ‘$[query]’ требует выражения
Я нашел аналогичную проблему, которая предлагает приведенное ниже исправление. Однако у меня это не работает:
Мой schema.graphql
:
type olatexOrders @model
@key(fields: ["PK", "SK"])
@key(name: "GSI-item-1", fields: ["GSIPKitem1", "GSISKitem1" ], queryField: "olatexOrdersByGSIPKitem1AndGSISKitem1")
@key(name: "GSI-order-1", fields: ["GSIPKorder1", "GSISKorder1" ], queryField: "olatexOrdersByGSIPKorder1AndGSISKorder1")
{
PK: String!
SK: String!
GSIPKitem1: String
GSISKitem1: String
GSIPKorder1: String
GSISKorder1: String
... and many more fields not relevant for this case
}
Ключ хэша (первичный ключ вторичный ключ) и оба GSI (GSI-item-1,
GSI-order1) были созданы правильно в DynamoDB. Я также могу запросить свой
Таблица DynamoDB из AppSync с использованием GSI:
query MyQuery {
olatexOrdersByGSIPKorder1AndGSISKorder1(GSIPKorder1: "IN_PROGRESS") {
nextToken
items {
GSIPKorder1
GSISKorder1
}
}
}
Однако это не работает, когда я пытаюсь использовать автоматически созданные классы усиления внутри
моего приложения для Android, как показано ниже:
private void query() {
AwsClientFactory.getInstance(context)
.query(OlatexOrdersByGsipKorder1AndGsisKorder1Query
.builder()
.gSIPKorder1(ORDER_STATUS_IN_PROGRESS)
.limit(200)
.build())
.responseFetcher(AppSyncResponseFetchers.NETWORK_ONLY)
.enqueue(callback);
}
Я получаю ту же ошибку, что и упомянутая выше. После прочтения соответствующей
проблемы я понимаю, что существует некоторая
ошибка / несоответствие / ограничение в том, как GSI реализованы в
AppSync и по этой причине вам необходимо указать не только первичный ключ
GSI, но также ключ сортировки и порядок сортировки. Обладая этими знаниями,
для тестирования я переписал свою функцию на:
private void query() {
AwsClientFactory.getInstance(context)
.query(OlatexOrdersByGsipKorder1AndGsisKorder1Query
.builder()
.gSIPKorder1(ORDER_STATUS_IN_PROGRESS)
.gSISKorder1(ModelStringKeyConditionInput.builder().beginsWith("K").build())
.sortDirection(ModelSortDirection.DESC)
.limit(200)
.build())
.responseFetcher(AppSyncResponseFetchers.NETWORK_ONLY)
.enqueue(callback);
}
К сожалению, я все еще получаю ту же ошибку:
Для блока выражения ‘$ [query]’ требуется выражение
Я использую Amplify CLI версии 4.27.2. Любая помощь будет оценена по достоинству!
РЕДАКТИРОВАТЬ 1
Я попытался упростить свой случай. Я создал GSI, имеющий только один столбец. Пожалуйста, смотрите schema.graphql
ниже:
type olatexOrders @model
@key(fields: ["PK", "SK"])
@key(name: "GSI-item-1", fields: ["GSIPKitem1"], queryField: "olatexOrdersByGSIItem")
@key(name: "GSI-order-1", fields: ["GSIPKorder1"], queryField: "olatexOrdersByGSIOrder")
{
PK: String!
SK: String!
GSIPKitem1: String
GSIPKorder1: String
... and many more fields not relevant for this case
}
Теперь я пытаюсь использовать приведенный ниже код для запроса моей динамической таблицы через Amplify amp; AppSync:
public class GetInProgressOrders {
private GraphQLCall.Callback<OlatexOrdersByGsiOrderQuery.Data> callback = new GraphQLCall.Callback<OlatexOrdersByGsiOrderQuery.Data>() {
@Override
public void onResponse(@Nonnull Response<OlatexOrdersByGsiOrderQuery.Data> response) {
try{
Log.d("MyTest", "TST response error: " errors.get(0).message());
}
catch (Exception e){
Log.e("MyTest", e.getMessage())
}
}
@Override
public void onFailure(@Nonnull ApolloException e) {
Log.e("MyTest", e.getMessage())
}
};
private void query(Context context){
AWSAppSyncClient awsClient = AwsClientFactory.getInstance(context);
OlatexOrdersByGsiOrderQuery tmpQuery = OlatexOrdersByGsiOrderQuery
.builder()
.gSIPKorder1(ORDER_STATUS_IN_PROGRESS)
.build();
awsClient.query(
tmpQuery
)
.responseFetcher(AppSyncResponseFetchers.NETWORK_ONLY)
.enqueue(callback);
}
}
Выполнение выше заканчивается той же ошибкой, что и ранее:
TST response error: Expression block '$[query]' requires an expression
Это дает мне ощущение, что я делаю что-то существенно неправильное. В принципе, я не могу запросить таблицу в Amplify через GSI. К сожалению, я не вижу своей ошибки.
С уважением
Ответ №1:
Это будет не совсем ответ, а обходной путь, который действительно работает.
Оказалось, у меня было несколько проблем, некоторые из которых были задокументированы лучше, некоторые хуже. Что я сделал, чтобы исправить свои коды:
- Для передачи данных из приложения Android в AWS AppSync используйте класс Amplify вместо класса AWSAppSyncClient.
- В schema.graphql не используйте поля только с заглавными буквами (в моем случае вместо использования PK amp; SK используйте pk amp; sk)
- В schema.graphql не создаются типы, начинающиеся со строчной буквы
- Создать столбец идентификатора идентификатора! введите (даже если вам это вообще не нужно)
Учитывая все вышесказанное, смотрите Мой schema.graphql, который действительно работает:
type OlatexOrders @model
@key(fields: ["pk", "sk"])
@key(name: "GSI-item-1", fields: ["gsi_pk_item_1", "gsi_sk_item_1"], queryField: "olatexOrdersByGSIItem")
@key(name: "GSI-order-1", fields: ["gsi_pk_order_1", "gsi_sk_order_1"], queryField: "olatexOrdersByGSIOrder")
{
pk: String!
sk: String!
gsi_pk_item_1: String
gsi_sk_item_1: String
gsi_pk_order_1: String
gsi_sk_order_1: String
... different not relevant fields
id: ID!
}
И мой запрос в приложении для Android:
Amplify.API.query(
ModelQuery.list(OlatexOrders.class, OlatexOrders.GSI_PK_ORDER_1.eq(ORDER_STATUS_IN_PROGRESS)),
response -> {
if(response.hasErrors())
Log.i("TestTag", "Errors: " response.getErrors().get(0));
if(response.hasData()){
for(OlatexOrders orders: response.getData()){
inProgressOrdersNames.add(orders.getGsiSkOrder_1());
}
}
else{
Log.i("TestTag", "No data");
}
},
error -> Log.e("TestTag", "Error", error)
);
С уважением!