Як отримати підрахунок предметів з DynamoDB?


83

Я хочу знати кількість елементів із запитами DynamoDB.

Я можу зробити запит щодо DynamoDB, але я хочу знати лише "загальна кількість елементів".

Наприклад, 'ВИБЕРИТИ КІЛЬКІСТЬ (*) З ... ДЕ ...' у MySQL

$result = $aws->query(array(
 'TableName' => 'game_table',
 'IndexName' => 'week-point-index',
 'KeyConditions' => array(
    'week' => array(
        'ComparisonOperator' => 'EQ',
        'AttributeValueList' => array(
            array(Type::STRING => $week)
        )
    ),
    'point' => array(
        'ComparisonOperator' => 'GE',
        'AttributeValueList' => array(
            array(Type::NUMBER => $my_point)
        )
    )
 ),
));
echo Count($result['Items']);

цей код отримує всі дані користувачів вище, ніж я вважаю.

Якщо підрахунок результату $ 100000, результат $ занадто великий. І це перевищило б межі розміру запиту.

Мені потрібна допомога.

Відповіді:


29

Ви можете використовувати Selectпараметр і використовуватиCOUNT в запиті. Він "повертає кількість відповідних елементів, а не самих відповідних елементів". Важливо , як зазначив Саумітра Р. Бхаве в коментарі : "Якщо розмір набору результатів запиту перевищує 1 МБ, тоді ScannedCount і Count представлятимуть лише частковий підрахунок загальної кількості елементів. Вам потрібно буде виконати кілька Операції запиту для отримання всіх результатів " .

Я не знайомий з PHP, але ось як ви можете використовувати його з Java. І тоді замість використання Count(що, на мою думку, є функцією в PHP) на, 'Items'ви можете використовувати Countзначення з відповіді - $result['Count']:

final String week = "whatever";
final Integer myPoint = 1337;
Condition weekCondition = new Condition()
        .withComparisonOperator(ComparisonOperator.EQ)
        .withAttributeValueList(new AttributeValue().withS(week));
Condition myPointCondition = new Condition()
        .withComparisonOperator(ComparisonOperator.GE)
        .withAttributeValueList(new AttributeValue().withN(myPoint.toString()))

Map<String, Condition> keyConditions = new HashMap<>();
keyConditions.put("week", weekCondition);
keyConditions.put("point", myPointCondition);

QueryRequest request = new QueryRequest("game_table");
request.setIndexName("week-point-index");
request.setSelect(Select.COUNT);
request.setKeyConditions(keyConditions);

QueryResult result = dynamoDBClient.query(request);
Integer count = result.getCount();

Якщо вам не потрібно емулювати WHEREпункт, ви можете використовувати DescribeTableзапит і використовувати отриманий підрахунок елементів, щоб отримати оцінку.

Кількість елементів у зазначеній таблиці. DynamoDB оновлює це значення приблизно кожні шість годин. Останні зміни можуть не відображатись у цьому значенні.

Крім того, важлива примітка з документації , зазначена Саумітрою Р. Бхаве в коментарях до цієї відповіді:

Якщо розмір Queryнабору результатів перевищує 1 МБ, ScannedCountі Countпредставляє лише частковий підрахунок загальної кількості елементів. Вам потрібно виконати кілька Queryоперацій, щоб отримати всі результати (див. Результати запитів таблиць з розподілом сторінок ).


17
Я думаю, що тут є невеликий улов, відповідно до docs.aws.amazon.com/amazondynamodb/latest/developerguide/…, який говорить: "Якщо розмір набору результатів запиту перевищує 1 Мб, тоді ScannedCount і Count представлятимуть лише частковий підрахунок загальної кількості предметів ", що в основному означає, що елементи спочатку отримують, а потім підраховують, і якщо розмір отриманих предметів перевищує 1 Мб, навіть" кількість "буде розбито на сторінки
— Саумітра Р. Бхаве

Я не хочу викрадати оригінальну роботу @ mkobit, але це спосіб зробити це, використовуючи вільний ланцюжок:AmazonDynamoDBClientBuilder.standard().withRegion(region).withCredentials(credentialsProvider).build() .query(new QueryRequest(freeKeysTableName).withSelect(Select.COUNT)).getCount()
— Шрідхар Сарнобат,

2
Просто для завершення Вашої відповіді, як зазначалося, можливо, Вам доведеться повторювати дзвінок, поки LastEvaluatedKey більше не буде присутній у результатах, і це може виглядати так (закінчується код вище): while(result.getLastEvaluatedKey()!=null){ request.setExclusiveStartKey(result.getLastEvaluatedKey()); result = dynamoDBClient.query(request); count+= result.getCount(); }
— Peter Koncz,

140

За допомогою aws dynamodb cli ви можете отримати його за допомогою сканування наступним чином:

aws dynamodb scan --table-name <TABLE_NAME> --select "COUNT"

Відповідь буде виглядати приблизно так:

{
    "Count": 123,
    "ScannedCount": 123,
    "ConsumedCapacity": null
}

зверніть увагу, що ця інформація в реальному часі на відміну від API таблиці описів


2
@JHH Я щойно спробував це, і, схоже, використовує одиниці ємності читання. За даними консолі DynamoDB, мій запит споживав близько 12 одиниць (налаштовано лише 1); Я припускаю, що він використовує пакетну потужність для обслуговування запиту.
— Зодман,

2
@Zodman дякую за спробу! Я ще раз прочитав документи і фактично знайшов твердження щодо підрахунків, які я раніше пропускав: "Отримання підрахунку елементів використовує однакову кількість одиниць ємності зчитування та підлягає однаковому обчисленню розміру елементів, тому що DynamoDB повинен прочитати кожен для збільшення кількості. " docs.aws.amazon.com/amazondynamodb/latest/developerguide/…
— JHH

2
Хтось може подумати, що кешування підрахунку, принаймні в послідовних межах, можливо, було б змусити його споживати лише одну єдину CU, але, можливо, отримання лише підрахунку не дуже поширений сценарій.
— JHH

2
@HelenNeely Так, таким чином забезпечується остання кількість елементів.
— Даніель Бубенхайм

1
Ця відповідь не є правильною, принаймні в контексті запитання. Питання полягає в тому, як отримати кількість записів, що відповідають виразу фільтра, отже, порівняння з оператором WHERE. AFAIK, намагаючись з’ясувати це протягом місяців, не дає змоги отримати кількість відповідних записів. dynamoDB пройде кожен запис у таблиці або індексі та поверне ті, що відповідають фільтру, 1000 записів одночасно. У вас може бути лише 20 відповідних записів, і ви отримаєте 20 як рахунок. Однак у наступних 1000 записах їх може бути 40 тощо.
— Chris Love

22

Це видно і з інтерфейсу користувача. Перейдіть на вкладку огляду в таблиці, ви побачите кількість елементів. Сподіваюся, це комусь допомагає.


6
Так, але це має обмеження: "Обсяг сховища та кількість предметів не оновлюються в режимі реального часу. Вони оновлюються періодично, приблизно кожні шість годин".
— Маттіас

Крім того, якщо ми хочемо бачити кількість запитів, це не можна зробити на вкладці Огляд. Він просто показує загальну кількість рядків у таблиці, а не кількість результатів мого запиту.
— Jyotsana Nandwani

7

Замініть назву таблиці та скористайтеся наведеним нижче запитом, щоб отримати дані про ваше локальне середовище:

aws dynamodb scan --table-name <TABLE_NAME> --select "COUNT" --endpoint-url http://localhost:8000

Замініть ім'я таблиці та видаліть URL-адресу кінцевої точки, щоб отримати дані про робоче середовище

aws dynamodb scan --table-name <TABLE_NAME> --select "COUNT"

6

Якщо вам вдалося зайти сюди, і ви працюєте з C #, ось код:

var cancellationToken = new CancellationToken();

var request = new ScanRequest("TableName") {Select = Select.COUNT};

var result = context.Client.ScanAsync(request, cancellationToken).Result;

totalCount = result.Count;

Це не працює, якщо у вас є більше 1 Мб елементів.
— JohnOpincar

1

Подібно до Java у наборі лише на PHP Виберіть ПАРАМЕТР зі значенням 'COUNT'

$result = $aws->query(array(
 'TableName' => 'game_table',
 'IndexName' => 'week-point-index',
 'KeyConditions' => array(
    'week' => array(
        'ComparisonOperator' => 'EQ',
        'AttributeValueList' => array(
            array(Type::STRING => $week)
        )
    ),
    'point' => array(
        'ComparisonOperator' => 'GE',
        'AttributeValueList' => array(
            array(Type::NUMBER => $my_point)
        )
    )
 ),
 'Select' => 'COUNT'
));

і звертається до нього просто так:

echo $ result ['Count'];

але оскільки Saumitra згаданий вище, будьте обережні з наборами результатів, більшими за 1 МБ, у цьому випадку використовуйте LastEvaluatedKey, поки він не поверне null, щоб отримати останнє оновлене значення підрахунку.


0

Ви можете використовувати запит mapper dynamodb.

PaginatedQueryList<YourModel> list = DymamoDBMapper.query(YourModel.class, queryExpression);
int count = list.size();

він викликає, loadAllResults()що буде ліниво завантажувати наступний доступний результат, поки allResultsLoaded.

Посилання: https://docs.amazonaws.cn/en_us/amazondynamodb/latest/developerguide/DynamoDBMapper.Methods.html#DynamoDBMapper.Methods.query


0
len(response['Items'])

дасть вам кількість відфільтрованих рядків

де,

fe = Key('entity').eq('tesla')
response = table.scan(FilterExpression=fe)

0

Я публікую цю відповідь для тих, хто використовує С #, хто хоче повністю функціональну, добре перевірену відповідь, яка демонструє використання запиту замість сканування. Зокрема, ця відповідь обробляє елементи, що підраховуються, розміром більше 1 Мб.

        public async Task<int> GetAvailableCount(string pool_type, string pool_key)
    {
        var queryRequest = new QueryRequest
        {
            TableName = PoolsDb.TableName,
            ConsistentRead = true,
            Select = Select.COUNT,
            KeyConditionExpression = "pool_type_plus_pool_key = :type_plus_key",
            ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
                {":type_plus_key", new AttributeValue { S =  pool_type + pool_key }}
            },
        };
        var t0 = DateTime.UtcNow;
        var result = await Client.QueryAsync(queryRequest);
        var count = result.Count;
        var iter = 0;
        while ( result.LastEvaluatedKey != null && result.LastEvaluatedKey.Values.Count > 0) 
        {
            iter++;
            var lastkey = result.LastEvaluatedKey.Values.ToList()[0].S;
            _logger.LogDebug($"GetAvailableCount {pool_type}-{pool_key} iteration {iter} instance key {lastkey}");
            queryRequest.ExclusiveStartKey = result.LastEvaluatedKey;
            result = await Client.QueryAsync(queryRequest);
            count += result.Count;
        }
        _logger.LogDebug($"GetAvailableCount {pool_type}-{pool_key} returned {count} after {iter} iterations in {(DateTime.UtcNow - t0).TotalMilliseconds} ms.");
        return count;
    }
}

-1

У Scala:

import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder
import com.amazonaws.services.dynamodbv2.document.DynamoDB
val client = AmazonDynamoDBClientBuilder.standard().build()

val dynamoDB = new DynamoDB(client)
val tableDescription = dynamoDB.getTable("table name").describe().getItemCount()

-2

Я використовував сканування, щоб отримати загальну кількість необхідного tableName. Наступне - фрагмент коду Java для цього самого

Long totalItemCount = 0;
do{
    ScanRequest req = new ScanRequest();
    req.setTableName(tableName);

    if(result != null){
        req.setExclusiveStartKey(result.getLastEvaluatedKey());
    }

    result = client.scan(req);

    totalItemCount += result.getItems().size();

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

System.out.println("Result size: " + totalItemCount);

-5

Це рішення для користувачів AWS JavaScript SDK, воно майже однакове для інших мов.

Result.data.Count дасть вам те, що ви шукаєте

 apigClient.getitemPost({}, body, {})

    .then(function(result){

        var dataoutput = result.data.Items[0];

        console.log(result.data.Count);
  }).catch( function(result){

});

2
Додайте пояснення до своєї відповіді.
— WonderWorker
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.