Java'da DynamoDB Query (AWS SDK v2)

AWS SDK for Java 2.x'teki queryPaginator bir koleksiyon gibi görünür ama değildir. Tembel ve yeniden yinelenebilir bir yapıdır ve fark, üzerinde ikinci kez döngü kurduğunuzda faturanızda ortaya çıkar. Query'nin ne zaman doğru okuma olduğu için bkz. Query ile Scan.

Kod

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.QueryRequest;
import software.amazon.awssdk.services.dynamodb.model.QueryResponse;

public class QueryExample {
    public static void main(String[] args) {
        try (DynamoDbClient ddb = DynamoDbClient.builder()
                .region(Region.US_EAST_1)
                .build()) {

            Map<String, String> names = new HashMap<>();
            names.put("#hashKey", "Artist");
            names.put("#rangeKey", "SongTitle");

            Map<String, AttributeValue> values = new HashMap<>();
            values.put(":hashKeyValue", AttributeValue.builder().s("Arturo Sandoval").build());
            values.put(":rangeKeyValue", AttributeValue.builder().s("C").build());

            QueryRequest request = QueryRequest.builder()
                    .tableName("Music")
                    .keyConditionExpression(
                            "#hashKey = :hashKeyValue AND begins_with(#rangeKey, :rangeKeyValue)")
                    .expressionAttributeNames(names)
                    .expressionAttributeValues(values)
                    .build();

            List<Map<String, AttributeValue>> items = new ArrayList<>();
            for (QueryResponse page : ddb.queryPaginator(request)) {
                items.addAll(page.items());
            }
            System.out.println("Found " + items.size() + " items");
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
        }
    }
}

QueryIterable her yinelemede sorguyu yeniden çalıştırır

Her şarkısı ~3,9 KB olan ve hepsi Artist = "Arturo Sandoval" altında bulunan 600 şarkılık bir düzenekte ddb.queryPaginator(request) 2,6 ms'de döndü ve hiçbir şey göndermedi. Sonra aynı QueryIterable nesnesi üzerinde iki kez döngü kuruldu:

queryPaginator(request) returned in 2.60 ms   (class QueryIterable, 0 requests)
iteration 1: pages=3  items=600  capacity=284.5
iteration 2: pages=3  items=600  capacity=284.5   <- same object

Tek bir değişken üzerinde iki for döngüsü, 569 okuma birimi. Sayfalar hiç önbelleğe alınmadı; her yineleme LastEvaluatedKey'i baştan yeniden yürür. Öğelere iki kez ihtiyacınız varsa, örnekte yapıldığı gibi yinelenebiliri bir kez bir List'e boşaltın.

Aynı tembelliğin diğer yüzü, hataların nerede yüzeye çıktığıdır. Anahtar koşulu bölüm anahtarını atlayan bir istek kurun; queryPaginator onu şikâyet etmeden kabul eder, çünkü henüz hiçbir çağrı gerçekleşmemiştir:

queryPaginator(bad) constructed without throwing
threw on iteration: DynamoDbException / ValidationException /
Query condition missed key schema element / http 400

Kurucunun etrafına sarılmış bir try-catch hiçbir şey yakalamaz. Döngüyü sarmalamak zorundadır; örneğin tüm bloğu tek bir try içine koymasının nedeni budur.

2026-07-28 tarihinde OpenJDK 26.0.1 üzerinde software.amazon.awssdk:dynamodb 2.49.4 ile, DynamoDB Local'e (amazon/dynamodb-local) karşı ölçüldü.

Açıklama

  • ddb.queryPaginator(request).items() sayfaları bir Iterable<Map<String, AttributeValue>> içinde düzleştirir ve sayfalamayı sizin arkanızda yapar; dolayısıyla yalnızca öğeleri istediğinizde örnekteki iki düzeyli döngü tek düzeye iner. Ayrıca bir SdkIterable'dır, yani .stream() de çalışır.
  • Kurucuda sayılar String'dir. AttributeValue.builder().n("1994"), .n(1994) için bir yazım hatası değildir — n() ayarlayıcısı bir java.lang.String alır, çünkü DynamoDB ikili float yuvarlamasından kaçınmak için sayıları ondalık metin olarak taşır. Java int geçirmek derlenmez.
  • keyConditionExpression bölüm anahtarında bir eşitlik artı en fazla bir sıralama anahtarı koşulu alır (=, <, <=, >, >=, BETWEEN, begins_with); .scanIndexForward(false) sırayı tersine çevirir ve .indexName("...") ikincil bir indeksi hedefler.
  • Enhanced Client diğer ergonomidir. software.amazon.awssdk.enhanced.dynamodb, Map<String, AttributeValue> yerine açıklamalı bean'leri eşler ve query'si yukarıda ölçülen aynı tembel yeniden yineleme semantiğine sahip bir PageIterable<T> döndürür.

Görsel olarak yapın

Bu örnekteki hem #hashKey hem de #rangeKey, hiçbir şeyin size dayatmadığı takma adlardır: ne Artist ne de SongTitle AWS'nin 573 sözcüklük ayrılmış listesindedir. Ayrılmış sözcük denetleyicisi, öznitelik adlarınızdan hangilerinin gerçekten # muamelesine ihtiyacı olduğunu söyler; böylece takma ad eşlemesi bir yük olmaktan çıkar.

QueryRequest'i kurmadan önce bir anahtar koşulunu gerçek bir tabloya karşı denemek için DynoTable'ı indirin ve sonuçlarda bir ızgarada sayfalayın.

İlgili örnekler

Kaynaklar

Bu isteği görsel olarak oluştur

Bu operasyonu ücretsiz DynamoDB Sorgu Oluşturucuda kur — anahtar koşulu, filtre, index, Limit, sıralama yönü ve bir sayfalama döngüsü — ve çalıştırılabilir bir SDK v3, CLI veya boto3 programı olarak geri kopyala.

DynamoDB Sorgu Oluşturucuyu aç

Console olmadan DynamoDB ile çalış

DynamoDB’nin çalıştıramadığı gerçek SQL’i çalıştıran hızlı bir DynamoDB masaüstü istemcisi — JOINs, GROUP BY, toplamalar — görsel düzenleme ve kendi Bedrock anahtarların üzerinde bir yapay zekâ aracısıyla.

30 günlük ücretsiz deneme, kredi kartı yok — ardından süre sınırı olmayan Ücretsiz plan.