python – Dynamodb scan() using FilterExpression

python – Dynamodb scan() using FilterExpression

This is because you used Pythons and keyword in your expression, instead of the & operator.

If a and b are both considered True, a and b returns the latter, b:

>>> 2 and 3
3

If any of them is False, or if both of them are, the first False object is returned:

>>> 0 and 3
0
>>> 0 and 
0
>>> 

The general rule is, and returns the first object that allows it to decide the truthiness of the whole expression.

Python objects are always considered True in boolean context. So, your expression:

Attr(Date).eq(date) and Attr(Shift).eq(shift)

will evaluate as the last True object, that is:

Attr(Shift).eq(shift)

which explains why you only filtered on the shift.

You need to use the & operator. It usually means bitwise and between integers in Python, it is redefined for Attr objects to mean what you want: both conditions.

So you must use the bitwise and:

FilterExpression=Attr(Date).eq(date) & Attr(Shift).eq(shift)

According to the documentation,

You are also able to chain conditions together using the logical
operators: & (and), | (or), and ~ (not).

Dynamodb scan() using FilterExpression

For multiple filters, you can use this approach:

import boto3
from boto3.dynamodb.conditions import Key, And

filters = dict()
filters[Date] = 2017-06-21
filters[Shift] = 3rd

response = table.scan(FilterExpression=And(*[(Key(key).eq(value)) for key, value in filters.items()]))

python – Dynamodb scan() using FilterExpression

Using parts from each of the above answers, heres a compact way I was able to get this working:

from functools import reduce
from boto3.dynamodb.conditions import Key, And

response = table.scan(FilterExpression=reduce(And, ([Key(k).eq(v) for k, v in filters.items()])))

Allows filtering upon multiple conditions in filters as a dict. For example:

{
    Status: Approved, 
    SubmittedBy: JackCasey
}

Leave a Reply

Your email address will not be published. Required fields are marked *