如何使用boto3在dynamodb的二级索引上进行查询?

62

是否有任何方法可以使用boto3查询DynamoDB的全局次要索引(global secondary index)。我没有找到任何在线教程或资源。

5个回答

127

在使用query函数时,您需要提供IndexName参数。

IndexName是索引的名称,通常与索引属性的名称不同(索引名称默认情况下具有-index后缀,尽管您可以在创建表时更改它)。例如,如果您的索引属性名为video_id,则您的索引名称可能是video_id-index

import boto3
from boto3.dynamodb.conditions import Key
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('videos')
video_id = 25
response = table.query(
    IndexName='video_id-index',
    KeyConditionExpression=Key('video_id').eq(video_id)
)

要检查索引名称,请前往AWS网页界面上表格的索引(Indexes)选项卡。您需要从名称(Name)列中获得一个值。


3
如果使用boto3客户端,请参见以下答案:https://dev59.com/dVsV5IYBdhLWcg3w0hlU#50122093 我无法弄清楚为什么key().eq()不能正常工作。 - GWed
2
运行得非常好,而且这也是一种简洁的做事方式。 - severin.julien
对我有用。请记住,GSI 应该具有所需的分区键(例如 'video_id')。 - William Choy
查询条件缺少关键模式元素:SK。有什么想法吗?我创建了一个名为SK-index的GSI,并将分区键设置为SK。如果使用Key("SK").eq(my_sk)来查询,虽然表中肯定存在具有SK的项,但返回的项目数为0。 - 404usernamenotfound

12

对于使用boto3客户端的任何人,下面的示例应该有效:

import boto3    

# for production
client = boto3.client('dynamodb')

# for local development if running local dynamodb server
client = boto3.client(
   'dynamodb',
   region_name='localhost',
   endpoint_url='http://localhost:8000'
)

resp = client.query(
   TableName='UsersTabe',
   IndexName='MySecondaryIndexName',
   ExpressionAttributeValues={
       ':v1': {
           'S': 'some@email.com',
       },
   },
   KeyConditionExpression='emailField = :v1',
)

# will always return list
items = resp.get('Items')

first_item = items[0]

4
为了让 Key() 起作用,你需要使用更高级别的 boto3.resourceTable 对象,而不是 boto3.client。你还需要从 boto3.dynamodb.conditions 中导入 Key(如果需要还要导入 Attr)。这里有一些难以找到的文档:https://boto3.amazonaws.com/v1/documentation/api/latest/reference/customizations/dynamodb.html#dynamodb-conditions。`Key` 的好处是,它将为您生成 KeyConditionExpression,而无需同时定义 ExpressionAttributeValuesExpressionAttributeNames - Davos

7

添加更新的技术:

    import boto3
    from boto3.dynamodb.conditions import Key, Attr

    dynamodb = boto3.resource(
         'dynamodb',
         region_name='localhost',
         endpoint_url='http://localhost:8000'
    )

    table = dynamodb.Table('userTable')

    attributes = table.query(
        IndexName='UserName',
        KeyConditionExpression=Key('username').eq('jdoe')
    )
    if 'Items' in attributes and len(attributes['Items']) == 1:
        attributes = attributes['Items'][0]


1

有很多类似的问题,因为通过boto3调用dynamo不是直观的。我使用dynamof库使这样的事情更加常识化。使用dynamof,调用看起来像这样。

from dynamof.operations import query
from dynamof.conditions import attr

query(
    table_name='users',
    conditions=attr('role').equals('admin'),
    index_name='role_lookup_index')

https://github.com/rayepps/dynamof

免责声明:我编写了dynamof


0
如上所述,要使用 GSI 查询 DynamoDB 表,您需要提供索引属性。您可以将索引属性作为参数输入,或者可以通过 client.describe_table() 搜索相应的索引属性。这样,您只需要提供表名和 GSI 即可。
import boto3
from boto3.dynamodb.conditions import Key
from botocore.exceptions import ClientError

ddb = boto3.resource('dynamodb', region_name='region_like_us_east_1')
index_attribute = None    
query_result = []

# assure you had checked table do exist, then to get gsi corresponding index attribute
table_attributes = ddb.meta.client.describe_table(TableName='your table name')
if 'GlobalSecondaryIndexes' in table_attributes['Table'] and len(table_attributes['Table']['GlobalSecondaryIndexes']) > 0:
    for each_index in table_attributes['Table']['GlobalSecondaryIndexes']:
        if each_index['IndexName'] == 'your gsi':
            index_attribute = each_index['KeySchema'][0]['AttributeName']

if index_attribute:
    try:
        response = ddb.table.query(IndexName='your gsi', KeyConditionExpression=Key(index_attribute).eq('your query value'))
        query_result = response['Items']
    except ClientError as err:
        exception_value = f"Can't query {table_name} by index: {gsi} =={gsi_value}, {err.response['Error']['Code']}: {err.response['Error']['Message']}"
        print(exception_value)
        raise ValueError(exception_value)
    finally:
        return query_result
else:
    warn_value = f"Can't find the index named as {'your gsi'}"
    print(warn_value)
    return query_result

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接