简体   繁体   中英

DynamoDB - How to query a nested attribute boto3

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?

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 fe year.

Therefore

table.scan(FilterExpression=Attr('info.genres').contains('Drama'))

should do the job

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM