Як отримати підрахунок предметів з 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.