DynamoDB - How to query a nested attribute boto3
Solution 1
You can use contains
to filter the data from List data type.
genres -attribute stored as List inside info
attribute which is a Map data type
FilterExpression=Attr('info.genres').contains('Drama')
Solution 2
Unlike in the accepted answer, to be able to filter all the items with the attribute, you need to use scan()
instead of query()
. query()
requires KeyCondition
which is unnecessary in your case and forces you to create condition containing f.e. year.
Therefore
table.scan(FilterExpression=Attr('info.genres').contains('Drama'))
should do the job
Dalton Sweeney
Updated on June 09, 2022Comments
-
Dalton Sweeney almost 2 years
I am following the DynamoDB python tutorial. This step shows how to query the table based on a specific key: http://docs.aws.amazon.com/amazondynamodb/latest/gettingstartedguide/GettingStarted.Python.04.html.
Here is the code for this query:
from __future__ import print_function # Python 2/3 compatibility import boto3 import json import decimal from boto3.dynamodb.conditions import Key, Attr # Helper class to convert a DynamoDB item to JSON. class DecimalEncoder(json.JSONEncoder): def default(self, o): if isinstance(o, decimal.Decimal): return str(o) return super(DecimalEncoder, self).default(o) dynamodb = boto3.resource('dynamodb', region_name='us-west-2', endpoint_url="http://localhost:8000") table = dynamodb.Table('Movies') print("Movies from 1992 - titles A-L, with genres and lead actor") response = table.query( ProjectionExpression="#yr, title, info.genres, info.actors[0]", ExpressionAttributeNames={ "#yr": "year" }, # Expression Attribute Names for Projection Expression only. KeyConditionExpression=Key('year').eq(1992) & Key('title').between('A', 'L') ) for i in response[u'Items']: print(json.dumps(i, cls=DecimalEncoder))
An example response item is
{ "title": "Juice", "year": "1992", "info": { "actors": [ "Omar Epps" ], "genres": [ "Crime", "Drama", "Thriller" ] } }
The table has the two key attributes 'title' and 'year' as well as the nested attribute 'info'. What I am trying to do is query the database and filter the movies by genre, for example get all Drama movies. I am not sure how to do this since the genre key is nested inside info.
I tried to get all the Drama movies from 1992 like this but it came up blank.
response = table.query( KeyConditionExpression=Key('year').eq(1992), FilterExpression=Attr('info.genres').eq('Drama') )
How do I properly filter this query with the nested info attribute?