Запрос DynamoDB с помощью GSI с использованием AppSync SDK и усиления CLI

#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:

Это будет не совсем ответ, а обходной путь, который действительно работает.
Оказалось, у меня было несколько проблем, некоторые из которых были задокументированы лучше, некоторые хуже. Что я сделал, чтобы исправить свои коды:

  1. Для передачи данных из приложения Android в AWS AppSync используйте класс Amplify вместо класса AWSAppSyncClient.
  2. В schema.graphql не используйте поля только с заглавными буквами (в моем случае вместо использования PK amp; SK используйте pk amp; sk)
  3. В schema.graphql не создаются типы, начинающиеся со строчной буквы
  4. Создать столбец идентификатора идентификатора! введите (даже если вам это вообще не нужно)

Учитывая все вышесказанное, смотрите Мой 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)
        );
 

С уважением!