简体   繁体   English

将 boto3 BaseCondition 转换为其字符串表示形式

[英]Convert boto3 BaseCondition to its string representation

I am trying to convert boto3 dynamoDB conditional expressions (using types from boto3.dynamodb.conditions) to its string representation.我正在尝试将 boto3 dynamoDB 条件表达式(使用 boto3.dynamodb.conditions 中的类型)转换为其字符串表示形式。 Of course this could be hand coded but naturally I would prefer to be able to find something developed by AWS itself.当然,这可以手动编码,但我自然希望能够找到 AWS 自己开发的东西。

Key("name").eq("new_name") & Attr("description").begins_with("new")

would become会成为

"name = 'new_name' and begins_with(description, 'new')"

I have been checking in the boto3 and boto core code but so far no success, but I assume it must exist somewhere in the codebase...我一直在检查 boto3 和 boto 核心代码,但到目前为止没有成功,但我认为它必须存在于代码库中的某个地方......

In the boto3.dynamodb.conditions module there is a class called ConditionExpressionBuilder .boto3.dynamodb.conditions模块中有一个名为ConditionExpressionBuilder的类。 You can convert a condition expression to string by doing the following:您可以通过执行以下操作将条件表达式转换为字符串:

condition = Key("name").eq("new_name") & Attr("description").begins_with("new")

builder = ConditionExpressionBuilder()
expression = builder.build_expression(condition, is_key_condition=True)

expression_string = expression.condition_expression
expression_attribute_names = expression.attribute_name_placeholders
expression_attribute_values = expression.attribute_value_placeholders

I'm not sure why this isn't documented anywhere.我不确定为什么这没有在任何地方记录。 I just randomly found it looking through the source code at the bottom of this page https://boto3.amazonaws.com/v1/documentation/api/latest/_modules/boto3/dynamodb/conditions.html .我只是随机发现它查看了本页面底部的源代码https://boto3.amazonaws.com/v1/documentation/api/latest/_modules/boto3/dynamodb/conditions.html

Unfortunately, this doesn't work for the paginator format string notation, but it should work for the Table.query() format.不幸的是,这不适用于分页格式字符串表示法,但它应该适用于Table.query()格式。

From @Brian's answer with ConditionExpressionBuilder I had to add the Dynamodb's {'S': 'value'} type notation before the query execution.从@Brian 对ConditionExpressionBuilder的回答中,我必须在查询执行之前添加 Dynamodb 的{'S': 'value'}类型表示法。

I changed it with expression_attribute_values[':v0'] = {'S': pk_value} , where :v0 is the first Key/Attr in the condition.我用expression_attribute_values[':v0'] = {'S': pk_value}更改了它,其中:v0是条件中的第一个键/属性。 Not sure but should work for next values (:v0, :v1, :v2...) .不确定,但应该适用于下一个值(:v0, :v1, :v2...)

Here is the full code, using pagination to retrieve only part of data这是完整的代码,使用分页只检索部分数据

from boto3.dynamodb.conditions import Attr, Key, ConditionExpressionBuilder
from typing import Optional, List
import boto3

client_dynamodb = boto3.client("dynamodb", region_name="us-east-1")

def get_items(self, pk_value: str, pagination_config: dict = None) -> Optional[List]:
    
    if pagination_config is None:
        pagination_config = {
            # Return only first page of results when no pagination config is not provided
            'PageSize': 300,
            'StartingToken': None,
            'MaxItems': None,
        }

    condition = Key("pk").eq(pk_value)

    builder = ConditionExpressionBuilder()
    expression = builder.build_expression(condition, is_key_condition=True)

    expression_string = expression.condition_expression
    expression_attribute_names = expression.attribute_name_placeholders
    expression_attribute_values = expression.attribute_value_placeholders

    # Changed here to make it compatible with dynamodb typing
    python expression_attribute_values[':v0'] = {'S': pk_value}

    paginator = client_dynamodb.get_paginator('query')
    page_iterator = paginator.paginate(
        TableName="TABLE_NAME",
        IndexName="pk_value_INDEX",
        KeyConditionExpression=expression_string,
        ExpressionAttributeNames=expression_attribute_names,
        ExpressionAttributeValues=expression_attribute_values,
        PaginationConfig=pagination_config
    )

    for page in page_iterator:
        resp=page
        break

    if ("Items" not in resp) or (len(resp["Items"]) == 0):
        return None

    return resp["Items"]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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