DynamoDB - 如何查询嵌套属性boto3

6
我正在跟随DynamoDB Python教程。这一步展示了如何基于特定的键查询表格:http://docs.aws.amazon.com/amazondynamodb/latest/gettingstartedguide/GettingStarted.Python.04.html
以下是此查询的代码:
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))

一个示例的响应项是:
{
    "title": "Juice",
    "year": "1992",
    "info": {
        "actors": [
            "Omar Epps"
        ],
        "genres": [
            "Crime",
            "Drama",
            "Thriller"
        ]
    }
}
表格
有两个关键属性'title'和'year',以及嵌套属性'info'。我想做的是查询数据库并通过类型过滤电影,例如获取所有的戏剧电影。我不确定如何做到这一点,因为类型键被嵌套在信息中。
我尝试过像这样获取1992年所有的戏剧电影,但没有结果。
response = table.query(
    KeyConditionExpression=Key('year').eq(1992),
    FilterExpression=Attr('info.genres').eq('Drama')
)

我该如何使用嵌套的info属性正确地过滤此查询?

DynamoDB旨在通过键进行查询,因此要实现您想要的功能,您将不得不查询整个表,并在获取它们后逐个查看条目。如果您知道自己会一遍又一遍地执行此类查询,我建议重新考虑使用DynamoDB的方式或选择要使用的键。 - mprat
好的,谢谢你的提示。 - Dalton Sweeney
由于 DynamoDb 不适合此用途,您有没有建议使用其他类型的数据库?我对数据库还很陌生。 - Dalton Sweeney
也许 MongoDB 对你的使用情况很合适。 - mprat
嘿,如果我的“genres”是一个对象数组,并且我想比较数组对象的属性,该怎么比较呢?例如:“genres”:[{"name":“犯罪”,description:“”},{"name":“戏剧”,description:“”},{"name":“惊悚”,description:“”}] 我想比较这个例子中的名称。 - Anmol Monga
2个回答

14
你可以使用contains过滤来自List数据类型的数据。 genres是存储在info属性中的List属性,info本身是一个Map数据类型。
FilterExpression=Attr('info.genres').contains('Drama')

1
嘿,如果我的“genres”是一个对象数组,并且我想比较数组对象的属性,该怎么比较呢?例如,“genres”: [ {"name":“Crime”,description:“”}, {"name":“Drama”,description:“”}, {"name":“Thriller”,description:“”} ] 我想比较这个示例中的名称。 - Anmol Monga
你仍然需要创建KeyCondition,如果你只想使用属性而不是Key呢?(所有戏剧,无论哪一年) - DavidS1992

1
与接受的答案不同,为了能够过滤具有该属性的所有项目,您需要使用 scan() 而不是 query()query() 需要 KeyCondition,这在您的情况下是不必要的,并且强制您创建包含年份等条件的条件。
因此,
table.scan(FilterExpression=Attr('info.genres').contains('Drama'))

应该做这项工作。

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