Java: запрос таблицы DynamoDB для всех значений ключа диапазона с помощью Mapper

#java #amazon-web-services #amazon-dynamodb

#java #amazon-web-services #amazon-dynamodb

Вопрос:

У меня есть таблица DynamoDB. Он имеет хэш-ключ «ID» и ключ диапазона «Category».

Я пытаюсь найти все записи для «Категории», например, comedy.

Это мой класс сопоставления:

 @DynamoDBTable(tableName = "Videos")
public class VideoDynamoMappingAdapter {

    private String videoID;
    private String videoCategory;
    private String videoArtist;
    private String videoTitle;

    @DynamoDBHashKey(attributeName = "ID")
    public String getVideoID() {
        return videoID;
    }

    public void setVideoID(String videoID) {
        this.videoID = videoID;
    }
    @DynamoDBRangeKey(attributeName = "Category")
    public String getVideoCategory() {
        return videoCategory;
    }

    public void setVideoCategory(String videoCategory) {
        this.videoCategory = videoCategory;
    }

    @DynamoDBAttribute(attributeName = "ArtistName")
    public String getVideoArtist() {
        return videoArtist;
    }

    public void setVideoArtist(String videoArtist) {
        this.videoArtist = videoArtist;
    }

    @DynamoDBAttribute(attributeName = "VideoTitle")
    public String getVideoTitle() {
        return videoTitle;
    }

    public void setVideoTitle(String videoTitle) {
        this.videoTitle = videoTitle;
    }

}
  

Я пытался запросить что-то вроде этого:

     DynamoDBQueryExpression<VideoDynamoMappingAdapter> queryExpression = new DynamoDBQueryExpression<VideoDynamoMappingAdapter>()
            .withRangeKeyCondition()


    List<VideoDynamoMappingAdapter> itemList = mapper.query(VideoDynamoMappingAdapter.class, queryExpression);
  

Я просматривал руководство, но не могу его понять, я бы подумал, что это будет простой запрос, который выполняется постоянно, поэтому, возможно, я что-то упускаю:

http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/QueryingJavaDocumentAPI.html#DocumentAPIJavaQueryExample

Заранее спасибо за вашу помощь

Ответ №1:

Notionquest был прав в своем ответе, что я не мог запросить все значения хэш-ключа в заданном состоянии диапазона. Я решил это, создав глобальный вторичный индекс для моего атрибута Category.

Это мой класс mapper:

 @ DynamoDBTable(tableName = "AlarmTable")
public class VideoDynamoMappingAdapter {

    private String videoID;
    private String videoCategory;
    private String videoArtist;
    private String videoTitle;

    @DynamoDBHashKey(attributeName = "ID")
    public String getVideoID() {
        return videoID;
    }

    public void setVideoID(String videoID) {
        this.videoID = videoID;
    }

    @DynamoDBIndexHashKey( globalSecondaryIndexName = "CategoryIndex", attributeName = "Category")
    public String getVideoCategory() {
        return videoCategory;
    }

    public void setVideoCategory(String videoCategory) {
        this.videoCategory = videoCategory;
    }

    @DynamoDBAttribute(attributeName = "VideoArtist")
    public String getVideoArtist() {
        return videoArtist;
    }

    public void setVideoArtist(String videoArtist) {
        this.videoArtist = videoArtist;
    }

    @DynamoDBAttribute(attributeName = "VideoTitle")
    public String getVideoTitle() {
        return videoTitle;
    }

    public void setVideoTitle(String videoTitle) {
        this.videoTitle = videoTitle;
    }

}
  

Обратите внимание на аннотацию к category для этого.

И тогда мой запрос выглядит так:

 VideoDynamoMappingAdapter videosToFind = new VideoDynamoMappingAdapter();
        videosToFind.setVideoCategory("Other");

        DynamoDBQueryExpression<VideoDynamoMappingAdapter> queryExpression = new DynamoDBQueryExpression<VideoDynamoMappingAdapter>()
                .withIndexName("CategoryIndex")
                .withHashKeyValues(videosToFind)
                .withConsistentRead(false);

        List<VideoDynamoMappingAdapter> itemList = mapper.query(VideoDynamoMappingAdapter.class, queryExpression);
        System.out.println("test"   itemList.size());
  

Я надеюсь, что это кому-то поможет.

Ответ №2:

Таблица DynamoDB не может быть запрошена только с помощью ключа диапазона без ключа хэша. Однако его можно запросить только с помощью хэш-ключа без ключа диапазона.

Когда таблица DynamoDB запрашивается только по ключу диапазона без ключа хэша, она выдает ValidationException ошибку .

 Unable to read item. Error JSON: {
  "message": "Query condition missed key schema element",
  "code": "ValidationException"
}
  

Альтернативным вариантом может быть сканирование базы данных с использованием ключа диапазона. Пожалуйста, обратите внимание, что сканирование DynamoDB является дорогостоящей операцией, поскольку она будет сканировать всю таблицу.

Сканирование таблицы видео по категориям:-

Пожалуйста, обратите внимание, что условие «ИЛИ» используется как «В» поддерживается только для определенных типов данных.

 public List<VideoDynamoMappingAdapter> getVidoesByCategory(String[] categories) {

        ScanResultPage<VideoDynamoMappingAdapter> videoResultPage = null;
        List<VideoDynamoMappingAdapter> videoList = new ArrayList<>();

        try {

            do {
                DynamoDBMapper dynamoDBMapper = new DynamoDBMapper(dynamoDBClient);

                Map<String, AttributeValue> expressionAttributeValues = new LinkedHashMap<String, AttributeValue>();

                StringBuilder filterExpression = new StringBuilder(); 
                int i = 1;

                for (String category : categories) {
                    if (i==1) {
                        filterExpression.append("Category = "   ":videoCategory"   i);  
                    } else {
                        filterExpression.append(" OR Category = "   ":videoCategory"   i);
                    }

                    expressionAttributeValues.put(":videoCategory"   i, new AttributeValue().withS(category));
                    i  ;
                }

                System.out.println("Filterexpression =====>"   filterExpression.toString());

                DynamoDBScanExpression scanExpression = new DynamoDBScanExpression()                
                        .withFilterExpression(filterExpression.toString())
                        .withExpressionAttributeValues(expressionAttributeValues);

                if (videoResultPage != null) {
                    scanExpression.setExclusiveStartKey(videoResultPage.getLastEvaluatedKey());
                }

                videoResultPage = dynamoDBMapper.scanPage(VideoDynamoMappingAdapter.class, scanExpression);

                System.out.println("Results ==========>"   videoResultPage.getResults());

                videoList.addAll(videoResultPage.getResults());

            } while (videoResultPage.getLastEvaluatedKey() != null);

        } catch (Exception db) {

            db.printStackTrace();

        }

        System.out.println(videoList.toString());
        return videoList;

    }
  

Комментарии:

1. Спасибо за ваш ответ. Можете ли вы показать мне, как запрашивать все хэши в диапазоне?

2. Добавлен код сканирования. Как упоминалось в моем предыдущем ответе, запрос невозможен без хэш-ключа.

3. Большое вам спасибо за ответ. Это показало мне, что мое понимание было неверным для документации. Я не думаю, что сканирование каждый раз является хорошим вариантом, поэтому я изменил его, чтобы добавить глобальный вторичный индекс, и я запрашиваю об этом.

4. Могу ли я попросить вас принять ответ как gsi, так и this? На данный момент ни одно из них не принято.

5. Я не могу принять два ответа. Поскольку вопрос в том, как я могу запросить. Я приму мое. Я поддержал ваш. Еще раз спасибо за вашу помощь.