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?
Nested attributes. An attribute is said to be nested if it is embedded within another attribute. To access a nested attribute, you use dereference operators: [n] — for list elements.
DynamoDB does support the complex condition on FilterExpression . Perfectly fine.
DynamoDB supports two different types of read operations, which are query and scan. A query is a lookup based on either the primary key or an index key. A scan is, as the name indicates, a read call that scans the entire table in order to find a particular result.
The Query operation took less than 65 milliseconds at the 95 percentile, compared to 650 milliseconds for Scan. In comparison to a query that conducts a straight lookup based on the partition key, response times vary substantially depending on the item and how the scan process works.
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')
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With