使用FilterExpression的Dynamodb scan()

2024-04-28 23:57:49 发布

您现在位置:Python中文网/ 问答频道 /正文

第一篇关于Stack的文章,对于使用Python和DynamoDB进行编程还比较陌生,但我只是想对表运行一个扫描,它返回基于两个预定义属性的结果。

---这是我的Python代码片段---

shift = "3rd"
date = "2017-06-21"

if shift != "":
    response = table.scan(
        FilterExpression=Attr("Date").eq(date) and Attr("Shift").eq(shift)
    )

我的发电机有四个磁场。

  1. 身份证
  2. 日期
  3. 移位
  4. 安全

DynamoDB Pic

现在的问题是,在运行时,我得到两个返回的表条目,而我应该只得到第一个条目。。。根据我的扫描标准,“没有安全问题”的那个。

---这是我的DynamoDB返回结果---

[
  {
    "Shift": "3rd",  
    "Safety": "No safety issues",  
    "Date": "2017-06-21",
    "ID": "2"
  }, 
  {
    "Shift": "3rd", 
    "Safety": "Cut Finger", 
    "Date": "2017-06-22", 
    "ID": "4"
  }
]

退回物品:2件

我相信,通过使用逻辑“和”应用FilterExpression,指定扫描操作将查找自我使用“和”以来同时满足这两个条件的条目。

这可能是因为在两个条目中都找到了“shift”属性“3rd”?我如何确保它返回的条目基于满足的两个条件,而不仅仅是给我一个属性类型的结果?

我觉得这很简单,但我已经查看了位于:http://boto3.readthedocs.io/en/latest/reference/services/dynamodb.html#DynamoDB.Table.scan的可用文档,仍然遇到了问题。任何帮助都将不胜感激!

另外,我试图保持帖子简单易懂(不包括我所有的程序代码),但是,如果需要额外的信息,我可以提供它!


Tags: iddatescanshift属性stack条目条件
3条回答

这是因为在表达式中使用了Python的and关键字,而不是&运算符。

如果ab都被认为是True,则a and b返回后者,b

>>> 2 and 3
3

如果其中任何一个是False,或者两者都是,则返回第一个False对象:

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

一般规则是,and返回第一个允许它决定整个表达式真实性的对象。

在布尔上下文中,Python对象总是被认为是True。所以,你的表情:

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

将计算为最后一个True对象,即:

Attr("Shift").eq(shift)

这就解释了为什么你只在轮班时过滤。

您需要使用&运算符。在Python中,它通常表示整数之间的“按位和”,它被重新定义为Attr对象表示您想要的内容:“两个条件”。

因此,必须使用“按位和”:

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

根据the documentation

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

使用FilterExpression的Dynamodb scan()

对于多个筛选器,可以使用以下方法:

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()]))

扩展Maxime Paille的答案,这涵盖了只有一个过滤器存在而有多个过滤器存在的情况。

from boto3.dynamodb.conditions import And, Attr

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

table.scan("my-table", **build_query_params(filters))

def build_query_params(filter_expressions):
    query_params = {}
    if len(filter_expressions) > 0:
        query_params["FilterExpression"] = add_expressions(filter_expressions)

    return query_params

def add_expressions(expressions: dict):
    if len(expressions) > 1:
        return And(*[(Attr(key).eq(value)) for key, value in expressions.items()])
    elif len(expressions) == 1:
        return [(Attr(key).eq(value)) for key, value in expressions.items()][0]

相关问题 更多 >