2016-04-21 9 views
10

Meine Tabelle ist rund 220mb mit 250k Datensätze drin. Ich versuche, alle diese Daten in Python zu ziehen. Mir ist klar, dass dies ein Chunked-Batch-Prozess sein muss und durchgeschleift werden muss, aber ich bin mir nicht sicher, wie ich die Chargen so einstellen kann, dass sie dort starten, wo der Vorgänger aufgehört hat.Kompletter Scan von dynamoDb mit boto3

Gibt es eine Möglichkeit, meinen Scan zu filtern? Von dem, was ich gelesen habe, tritt das Filtern nach dem Laden auf und das Laden stoppt bei 1 MB, so dass ich tatsächlich nicht in der Lage wäre, neue Objekte einzuscannen.

Jede Hilfe wäre willkommen.

import boto3 
dynamodb = boto3.resource('dynamodb', 
    aws_session_token = aws_session_token, 
    aws_access_key_id = aws_access_key_id, 
    aws_secret_access_key = aws_secret_access_key, 
    region_name = region 
    ) 

table = dynamodb.Table('widgetsTableName') 

data = table.scan() 

Antwort

-1

Stellt sich heraus, dass Boto3 den "LastEvaluatedKey" als Teil der zurückgegebenen Antwort erfasst. Dies kann für einen Scan als Startpunkt verwendet werden:

data= table.scan(
    ExclusiveStartKey=data['LastEvaluatedKey'] 
) 

ich auf den Aufbau einer Schleife um diese bis zum zurückgegebenen Daten planen nur die ExclusiveStartKey

15

boto3 Paginatoren bietet, die für Sie alle Paginierung Details Griff . Here ist die Dokumentseite für den Scan-Paginator. Grundsätzlich würden Sie es so verwenden:

import boto3 

client = boto3.client('dynamodb') 
paginator = client.get_paginator('scan') 

for page in paginator.paginate(): 
    # do something 
+2

Beachten Sie, dass die Elemente in 'Seite [‘ Elemente ']' ist möglicherweise nicht das, was Sie erwarten: Da dieser Paginator schmerzhaft generisch ist, erhalten Sie für jedes DynamoDB-Objekt ein Wörterbuch des Formattyps: value, z '{'myAttribute': {'M': {}}, 'IhrAttribut': {'N': u'132457 '}}' für eine Zeile mit einer leeren Map und einem numerischen Typ (der als String zurückgegeben wird, der Es muss "decimal.Decimal" vorgeschlagen werden, da es bereits eine Zeichenfolge benötigt und nicht ganzzahlige Zahlen behandelt. Andere Arten, z.B. Strings, Maps und Booleans werden von Boto in ihre Python-Typen konvertiert. – kungphu

+0

ist es möglich, einen Scan-Filter oder Filter-Ausdruck mit Paginierung zu haben? – vnpnlz

+0

Paginators wäre großartig, wenn es nicht für das Problem wäre @kungphu angehoben. Ich sehe nicht die Verwendung für etwas, das eine nützliche Sache tut, aber negiert es durch die Verschmutzung der Antwortdaten mit irrelevanten Metadaten –

4

Code zum Löschen dynamodb Formattyp als @kungphu erwähnt.

import boto3 

from boto3.dynamodb.types import TypeDeserializer 
from boto3.dynamodb.transform import TransformationInjector 

client = boto3.client('dynamodb') 
paginator = client.get_paginator('query') 
service_model = client._service_model.operation_model('Query') 
trans = TransformationInjector(deserializer = TypeDeserializer()) 
for page in paginator.paginate(): 
    trans.inject_attribute_value_output(page, service_model) 
+0

Bravo! negiert meinen früheren Kommentar über den Mangel an Nützlichkeit von Paginatoren. Vielen Dank! Warum ist das nicht das Standardverhalten? –

11

Ich denke, die Amazon DynamoDB documentation in Bezug auf Tabelle Scannen Ihre Frage beantwortet.

Kurz gesagt, müssen Sie in der Antwort auf LastEvaluatedKey überprüfen. Hier ist ein Beispiel Ihres Code verwendet:

import boto3 
dynamodb = boto3.resource('dynamodb', 
          aws_session_token=aws_session_token, 
          aws_access_key_id=aws_access_key_id, 
          aws_secret_access_key=aws_secret_access_key, 
          region_name=region 
) 

table = dynamodb.Table('widgetsTableName') 

response = table.scan() 
data = response['Items'] 

while 'LastEvaluatedKey' in response: 
    response = table.scan(ExclusiveStartKey=response['LastEvaluatedKey']) 
    data.extend(response['Items']) 
+7

Während dies funktioniert, beachten Sie, dass die [boto3 Dokumentation] (http://boto3.readthedocs.io/en/latest/reference/services/dynamodb.html#DynamoDB.Client.query) angibt _ Wenn LastEvaluatedKey leer ist, dann die "Letzte Seite" der Ergebnisse wurde verarbeitet, und es gibt keine weiteren Daten, die abgerufen werden können. Der Test, den ich verwende, ist also 'while response.get (' LastEvaluatedKey ')' anstatt 'LastEvaluatedKey' als Antwort ', Nur weil "leer ist" bedeutet nicht unbedingt "ist nicht vorhanden", und das funktioniert in jedem Fall. – kungphu

+0

Paginator ist eine bequemere Möglichkeit, um abgefragte/gescannte Objekte zu durchlaufen – iuriisusuk

4

Riffing weg von Jordon Phillips Antwort, hier, wie Sie eine FilterExpression in der Paginierung passieren würden:

import boto3 

client = boto3.client('dynamodb') 
paginator = client.get_paginator('scan') 
operation_parameters = { 
    'TableName': 'foo', 
    'FilterExpression': 'bar > :x AND bar < :y', 
    'ExpressionAttributeValues': { 
    ':x': {'S': '2017-01-31T01:35'}, 
    ':y': {'S': '2017-01-31T02:08'}, 
    } 
} 

page_iterator = paginator.paginate(**operation_parameters) 
for page in page_iterator: 
    # do something