boto3&rsod; dynamodb的AWS示例过于简单化。我想抛出一个Web表单,允许用户选择表中的任何元素,或者为任何单个字段和AND所有字段过滤器提供多个选项。
要做到这一点,我需要构建一系列OR条件,然后和所有结果或组合,如: 和([或([c1,c2,...]),或([e1,e ...]),或([a1,a ...])])
我不知道每个Or的术语数量,或者直到运行时的最终和,所以我需要能够在运行时聚合过滤器术语。
对于下面的所有问题,这里是我的FilterExpressions集:
c1 = Attr('class').eq(2)
c2 = Attr('class').eq(3)
c = Or([c1, c2])
e1 = Attr('exclusion').eq(0)
a1 = Attr('action').eq(2)
我能够进行简单的和/或查询:
结合2和条件:
all = [a1, e1]
request = {'ConsistentRead': False, 'FilterExpression': And(*all)}
print ('dynamo scan params: {}'.format(request))
response = table.scan(**request)
print response['Count'], response['ScannedCount']
dynamo scan params: {'FilterExpression': <boto3.dynamodb.conditions.And object at 0x115d7d410>, 'ConsistentRead': False}
34 1166
结合2或条件:
all = [c1,c2]
request = {'ConsistentRead': False, 'FilterExpression': Or(*all)}
print ('dynamo scan params: {}'.format(request))
response = table.scan(**request)
print response['Count'], response['ScannedCount']
dynamo scan params: {'FilterExpression': <boto3.dynamodb.conditions.Or object at 0x115d7dc90>, 'ConsistentRead': False}
51 1166
结合多个And和Or条件:
我希望此处的语法不正确,但我无法在AWS或boto文档中找到任何此类示例。
all = [And([a1,e1]), Or([c1,c2])]
那就是我被困的地方。
答案 0 :(得分:0)
这有效,但感觉不是很理想:
# 2 params are clazz and exclusion which are lists of matches
# to be OR's together individually and ANDed at the end.
# these map to the dynamo fields 'class' and 'exclusion'
# Start with an empty aggregator filter:
fe = None
# I'm iterating over each "OR" item:
# class is a list of enum values that should match in an OR condition
if clazz:
fe_class = None
for x in clazz:
fe_x = Attr('class').eq(ArticleClass[x].value)
if not fe_class:
fe_class = fe_x
else:
fe_class = (fe_class | fe_x)
# Then appending it as an "AND" item to a running total:
if fe:
# If there's an existing fe, append this
fe = (fe & fe_class)
else:
# otherwise this is the starting point
fe = fe_class
# Next "OR" term
# exclusion is also a list of enum values that should match in an OR condition
if exclusion:
fe_exclusion = None
for x in exclusion:
fe_x = Attr('exclusion').eq(ArticleExclusion[x].value)
if not fe_exclusion:
fe_exclusion = fe_x
else:
fe_exclusion = (fe_exclusion | fe_x)
# "AND"ed together again:
if fe:
# If there's an existing fe, append this
fe = (fe & fe_exclusion)
else:
# otherwise this is the starting point
fe = fe_exclusion
# If the aggregated filter has any Attr's in it, add to request
if fe:
request['FilterExpression'] = fe
response = table.scan(**request)
喜欢知道是否有更好的方式。