Is there a way at all to query on the global secondary index
of dynamodb using boto3
. I dont find any online tutorials or resources.

- 1,800
- 3
- 29
- 51
4 Answers
You need to provide an IndexName
parameter for the query
function.
This is the name of the index, which is usually different from the name of the index attribute (the name of the index has an -index
suffix by default, although you can change it during table creation). For example, if your index attribute is called video_id
, your index name is probably 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)
)
To check the index name, go to the Indexes
tab of the table on the web interface of AWS. You'll need a value from the Name
column.

- 4,904
- 5
- 27
- 34
-
3if using boto3 client, see answer below https://stackoverflow.com/a/50122093/1085343 i couldnt get key().eq() to work for some reason – GWed May 01 '18 at 18:50
-
2Work like a charm, also it's a succinct way of doing things. – severin.julien Jun 20 '18 at 08:46
-
Worked for me. Remember the GSI should have the desired partition key (ex 'video_id') – William Choy Sep 25 '19 at 18:09
-
"Query condition missed key schema element: SK" -- Any ideas? Made a GSI called SK-index and set the partition key to SK. Querying using `Key("PK").eq(my_sk)`. If using `Key("SK").eq(my_sk)` instead, it returns 0 items, even though items with `SK`s definitely exist in the table. – 404usernamenotfound Aug 04 '23 at 16:52
For anyone using the boto3 client, below example should work:
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]

- 15,167
- 5
- 62
- 99
-
4To get `Key()` working you need to use the higher level `boto3.resource` and then the `Table` object, not the `boto3.client`. You also need to import `Key` (and `Attr` if needed) from `boto3.dynamodb.conditions` . There's some hard to find docs on this here: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/customizations/dynamodb.html#dynamodb-conditions The nice thing about Key is that it will generate the `KeyConditionExpression` for you without having to also define `ExpressionAttributeValues` and `ExpressionAttributeNames` – Davos Nov 21 '18 at 01:07
Adding the updated technique:
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]

- 899
- 8
- 6
There are so many questions like this because calling dynamo through boto3 is not intuitive. I use dynamof
library to make things like this a lot more common sense. Using dynamof
the call looks like this.
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
disclaimer: I wrote dynamof

- 2,072
- 1
- 12
- 22