Monday, 6 January 2020

Amazon DynamoDB 入门8:删除项目

从表中删除数据

在 SQL 中,DELETE 语句从表中删除一个或多个行。DynamoDB 使用 DeleteItem 操作一次删除一个项目。

SQL

在 SQL 中,可使用 DELETE 语句删除一个或多个行。WHERE 子句确定要修改的行。示例如下:
DELETE FROM Music
WHERE Artist = 'The Acme Band' AND SongTitle = 'Look Out, World';
我们可以修改 WHERE 子句以删除多个行。例如,删除某个特殊艺术家的所有歌曲,如下所示:
DELETE FROM Music WHERE Artist = 'The Acme Band'

Note

如果省略 WHERE 子句,则数据库会尝试从表中删除所有行。

DynamoDB

在 DynamoDB 中,可使用 DeleteItem 操作修改单个项目。
{
   "ConditionExpression": "string",
   "ExpressionAttributeNames": {
      "string" : "string"
   },
   "ExpressionAttributeValues": {
      "string" : {
         "B": blob,
         "BOOL": boolean,
         "BS": [ blob ],
         "L": [
            "AttributeValue"
         ],
         "M": {
            "string" : "AttributeValue"
         },
         "N": "string",
         "NS": [ "string" ],
         "NULL": boolean,
         "S": "string",
         "SS": [ "string" ]
      }
   },
   "Key": {
      "string" : {
         "B": blob,
         "BOOL": boolean,
         "BS": [ blob ],
         "L": [
            "AttributeValue"
         ],
         "M": {
            "string" : "AttributeValue"
         },
         "N": "string",
         "NS": [ "string" ],
         "NULL": boolean,
         "S": "string",
         "SS": [ "string" ]
      }
   },
   "ReturnConsumedCapacity": "string",
   "ReturnItemCollectionMetrics": "string",
   "ReturnValues": "string",
   "TableName": "string"
}
参数说明:
  • Key: 主键,用于定位项目
  • TableName:表名 (最小 3. 最大 255)
  • ConditionExpression:条件表达式(仅在特定 ConditionExpression 的计算结果为 true 时成功完成)
  • ExpressionAttributeNames:条件表达式的名称的别名,比如 date 为保留字,可用别名定义为 #d
  • ExpressionAttributeValues:条件表达式的值
  • ReturnConsumedCapacity:显示使用的写入容量单位数
    • TOTAL 会返回由表及其所有global secondary index占用的写入容量;
    • INDEXES 仅返回由global secondary index占用的写入容量;
    • NONE 表示您不需要返回任何占用容量统计数据。
  • ReturnValues: 更新后返回的数据.
    • NONE - 如果没有特别说明,返回None (这个是默认值)
    • ALL_OLD - 按在进行更新之前的情况,返回整个项目。
  • ReturnItemCollectionMetrics: Determines whether item collection metrics are returned. If set to SIZE , the response includes statistics about item collections, if any, that were modified during the operation are returned in the response. If set to NONE (the default), no statistics are returned.
response = table.delete_item(
    Key={
        'string': 'string'|123|Binary(b'bytes')|True|None|set(['string'])|set([123])|set([Binary(b'bytes')])|[]|{}
    },
    ConditionalOperator='AND'|'OR',
    ReturnValues='NONE'|'ALL_OLD'|'UPDATED_OLD'|'ALL_NEW'|'UPDATED_NEW',
    ReturnConsumedCapacity='INDEXES'|'TOTAL'|'NONE',
    ReturnItemCollectionMetrics='SIZE'|'NONE',
    ConditionExpression=Attr('myattribute').eq('myvalue'),
    ExpressionAttributeNames={
        'string': 'string'
    },
    ExpressionAttributeValues={
        'string': 'string'|123|Binary(b'bytes')|True|None|set(['string'])|set([123])|set([Binary(b'bytes')])|[]|{}
    }
)
在 DynamoDB 中,可使用 DeleteItem 操作从表中删除数据(一次删除一个项目)。必须指定项目的主键值。示例如下:
{
    TableName: "Music",
    Key: {
        Artist: "The Acme Band",
        SongTitle: "Look Out, World"
    }
}

Note

除了 DeleteItem 之外,Amazon DynamoDB 还支持同时删除多个项目的 BatchWriteItem 操作。
DeleteItem 支持条件写入,在此情况下,操作仅在特定 ConditionExpression 的计算结果为 true 时成功完成。例如,以下 DeleteItem 操作仅在项目具有 RecordLabel 属性时删除项目:
{
    TableName: "Music",
    Key: {
        Artist: "The Acme Band",
        SongTitle: "Look Out, World"
    },
   ConditionExpression: "attribute_exists(RecordLabel)"
}
删除操作就这么简单,下边是福利时间。
是不是每次用boto3 操作DynamoDB 都有种痛不欲生的感觉,下边我们介绍一个新工具。

dynamodb-py

dynamodb-py 是模仿sqlalchemy 编写的DynamoDB ORM 它的使用方法特别简单,下边来看几个示例:
表的操作
from dynamodb.model import Model
from dynamodb.fields import CharField, IntegerField, FloatField, DictField
from dynamodb.table import Table

class Movies(Model):

    __table_name__ = 'Movies'

    ReadCapacityUnits = 10
    WriteCapacityUnits = 10

    year = IntegerField(name='year', hash_key=True)
    title = CharField(name='title', range_key=True)
    rating = FloatField(name='rating', indexed=True)
    rank = IntegerField(name='rank', indexed=True)
    release_date = CharField(name='release_date')
    info = DictField(name='info', default={})

# create_table
Table(Movies()).create()

# update_table
Table(Movies()).update()

# delete_table
Table(Movies()).delete()
查询项目
# query without index
items = Movies.query().where(Movies.year.eq(year)).all()
items = Movies.query().where(Movies.year.eq(1985)).limit(10).all()
items = (Movies.query()
        .where(Movies.year.eq(1992),
               Movies.title.between('A', 'L'))
        .all())

# query with index
items = (Movies.query()
        .where(Movies.year.eq(1992),
               Movies.title.between('A', 'L'))
        .order_by(Movies.rating, asc=False)
        .all())
更新项目
item = Movies.get(year=year, title=title)

item.update(rank=2467, rating=7.1)
删除项目
item = Movies.get(year=year, title=title)

item.delete()
就是这么方便。
不过dynamodb-py 还在开发中,欢迎试用,也欢迎贡献自己的力量。
终于,下一节介绍索引的查询

from : https://segmentfault.com/a/1190000008707650

Amazon DynamoDB 入门7:项目更新

update (修改表中的数据)

SQL 语言提供用于修改数据的 UPDATE 语句。DynamoDB 使用 UpdateItem 操作完成类似的任务。

SQL

在 SQL 中,可使用 UPDATE 语句修改一个或多个行。SET 子句为一个或多个列指定新值,WHERE 子句确定修改的行。示例如下:
UPDATE Music
SET RecordLabel = 'Global Records'
WHERE Artist = 'No One You Know' AND SongTitle = 'Call Me Today';
如果任何行均不匹配 WHERE 子句,则 UPDATE 语句不起作用。

DynamoDB

在 DynamoDB 中,可使用 UpdateItem 操作修改单个项目。
API 语法如下:
{
   "AttributeUpdates": {
      "string" : {
         "Action": "string",
         "Value": {
            "B": blob,
            "BOOL": boolean,
            "BS": [ blob ],
            "L": [
               "AttributeValue"
            ],
            "M": {
               "string" : "AttributeValue"
            },
            "N": "string",
            "NS": [ "string" ],
            "NULL": boolean,
            "S": "string",
            "SS": [ "string" ]
         }
      }
   },
   "ConditionalOperator": "string",
   "ConditionExpression": "string",
   "Expected": {
      "string" : {
         "AttributeValueList": [
            {
               "B": blob,
               "BOOL": boolean,
               "BS": [ blob ],
               "L": [
                  "AttributeValue"
               ],
               "M": {
                  "string" : "AttributeValue"
               },
               "N": "string",
               "NS": [ "string" ],
               "NULL": boolean,
               "S": "string",
               "SS": [ "string" ]
            }
         ],
         "ComparisonOperator": "string",
         "Exists": boolean,
         "Value": {
            "B": blob,
            "BOOL": boolean,
            "BS": [ blob ],
            "L": [
               "AttributeValue"
            ],
            "M": {
               "string" : "AttributeValue"
            },
            "N": "string",
            "NS": [ "string" ],
            "NULL": boolean,
            "S": "string",
            "SS": [ "string" ]
         }
      }
   },
   "ExpressionAttributeNames": {
      "string" : "string"
   },
   "ExpressionAttributeValues": {
      "string" : {
         "B": blob,
         "BOOL": boolean,
         "BS": [ blob ],
         "L": [
            "AttributeValue"
         ],
         "M": {
            "string" : "AttributeValue"
         },
         "N": "string",
         "NS": [ "string" ],
         "NULL": boolean,
         "S": "string",
         "SS": [ "string" ]
      }
   },
   "Key": {
      "string" : {
         "B": blob,
         "BOOL": boolean,
         "BS": [ blob ],
         "L": [
            "AttributeValue"
         ],
         "M": {
            "string" : "AttributeValue"
         },
         "N": "string",
         "NS": [ "string" ],
         "NULL": boolean,
         "S": "string",
         "SS": [ "string" ]
      }
   },
   "ReturnConsumedCapacity": "string",
   "ReturnItemCollectionMetrics": "string",
   "ReturnValues": "string",
   "TableName": "string",
   "UpdateExpression": "string"
}
参数说明:
  • Key: 主键,用于定位项目
  • TableName:表名 (最小 3. 最大 255)
  • Expected:
  • AttributeUpdates: 遗留参数,已废弃
  • ConditionalOperator: 遗留参数,已废弃
  • ConditionExpression:条件表达式(仅在特定 ConditionExpression 的计算结果为 true 时成功完成)
  • ExpressionAttributeNames:条件表达式的名称的别名,比如 date 为保留字,可用别名定义为 #d
  • ExpressionAttributeValues:条件表达式的值
  • ReturnConsumedCapacity:显示使用的写入容量单位数
    • TOTAL 会返回由表及其所有global secondary index占用的写入容量;
    • INDEXES 仅返回由global secondary index占用的写入容量;
    • NONE 表示您不需要返回任何占用容量统计数据。
  • ReturnValues: 更新后返回的数据.
    • NONE - 如果没有特别说明,返回None (这个是默认值)
    • ALL_OLD - 按在进行更新之前的情况,返回整个项目。
    • ALL_NEW - 按在进行更新之后的情况,返回整个项目。
    • UPDATED_OLD - 按在进行更新之前的情况,仅返回更新的值。
    • UPDATED_NEW - 按在进行更新之后的情况,仅返回更新的值。
  • UpdateExpression:指定要修改的属性以及这些属性的新值,更新表达式还指定如何修改属性。下面是更新表达式的语法摘要:
update-expression ::=
SET set-action , ...
| REMOVE remove-action , ...  
| ADD add-action , ...
| DELETE delete-action , ...  
更新表达式由多个部分组成。每个部分以一个 SET、REMOVE、ADD 或 DELETE 关键字开头。您可在更新表达式中按任意顺序包含其中任意部分。但是,每个部分关键字只能出现一次。您可以同时修改多个属性。以下是更新表达式的一些示例:
  • SET list[0] = :val1
  • REMOVE #m.nestedField1, #m.nestedField2
  • ADD aNumber :val2, anotherNumber :val3
  • DELETE aSet :val4
以下示例显示了带有多个部分的单个更新表达式:
SET list[0] = :val1 REMOVE #m.nestedField1#m.nestedField2 ADD aNumber :val2, anotherNumber :val3 DELETE aSet :val4
我们可以在更新表达式中使用任意属性名称,第一个字符是 a-z 或 A-Z第二个字符(如果存在)是 a-z、A-Z 或 0-9
如果属性名称不满足此要求,则需要将表达式属性名称定义为占位符。更多信息参考(表达式属性名称)。
要在更新表达式中指定文本值,可以使用表达式属性值。更多信息参考(表达式属性值)。

SET
在更新表达式中使用 SET 操作可将一个或多个属性与值添加到项目。如果这些属性已存在,则更新。还可以使用 SET 来加或减数字类型的属性。对多个属性执行 SET 操作,使用逗号分隔。
set语法如下:
set-action ::=
    path = value

value ::=
    operand
    | operand '+' operand
    | operand '-' operand

operand ::=
    path | function
  • path 元素是项目的文档路径。(比如项目中info 为字典 info 中 a 的路径为info['a'])
  • operand 元素可以为项目的文档路径,或者为函数。
SET 操作支持以下函数:
  • if_not_exists (path, operand) - 如果项目在指定 path 中不包含属性,则 if_not_exists 的求值结果为 operand;否则求值结果为 path。您可以使用此函数来避免覆盖项目中已存在的属性。
  • list_append (operand, operand) - 此函数的求值结果为列表,新元素将添加到列表中。新元素必须包含在列表中,例如要向列表中添加 2,操作数将成为 [2]。您可以通过反转操作数的顺序,将新元素附加到列表的开头或结尾。
以下是在这些函数中使用 SET 操作的一些示例。
如果属性已存在,则以下示例不执行任何操作;否则它会将属性设置为默认值。
SET Price = if_not_exists(Price, 100)
以下示例将新元素添加到 FiveStar 评论列表。表达式属性名称 #pr 是 ProductReviews;属性值 :r 是只包含一个元素的列表。如果列表之前有两个元素 [0] 和 [1],则新元素将为 [2]。
SET #pr.FiveStar = list_append(#pr.FiveStar, :r)
以下示例将另一个元素添加到 FiveStar 评论列表中,但此时元素将附加到列表开头的位置 [0] 处。列表中的所有其他元素将会移动一位。
SET #pr.FiveStar = list_append(:r, #pr.FiveStar)
REMOVE
在更新表达式中使用 REMOVE 操作可从项目中删除一个或多个元素。要执行多个 REMOVE 操作,请使用逗号分隔。
下面是更新表达式中的 REMOVE 的语法摘要。唯一的操作数是您要删除的属性的文档路径:
remove-action ::=
    path
以下是使用 REMOVE 操作的更新表达式示例。从项目中删除多个属性:
REMOVE Title, RelatedItems[2], Pictures.RearView
对列表元素使用 REMOVE
当删除现有列表元素时,剩余的元素将会移位。例如,考虑以下列表:
MyNumbers: { ["Zero","One","Two","Three","Four"] }
列表包含元素 [0]、[1]、[2]、[3] 和 [4]。现在,我们使用 REMOVE 操作删除两个元素:
REMOVE MyNumbers[1], MyNumbers[3]
剩余的元素会向右移位,生成带有元素 [0]、[1] 和 [2] 的列表,每个元素具有以下数据:
MyNumbers: { ["Zero","Two","Four"] }
如果您使用 REMOVE 来删除超出列表中最后一个元素位置的不存在项目,则将不执行任何操作:也就是不删除任何数据。例如,以下表达式对 MyNumbers 列表没有任何效果:
REMOVE MyNumbers[11]
ADD
ADD 操作仅支持数字和集数据类型。一般而言,我们建议使用 SET 而不是 ADD。
在更新表达式中使用 ADD 可执行以下任一操作:
  • 如果属性尚不存在,则将新属性及其值添加到项目。
  • 如果属性已存在,则 ADD 的行为取决于属性的数据类型:
  • 如果属性是数字,并且添加的值也是数字,则该值将按数学运算与现有属性相加。(如果该值为负数,则从现有属性减去该值。)
  • 如果属性是集,并且您添加的值也是集,则该值将附加到现有集中。
  • 要执行多个 ADD 操作,请使用逗号分隔。
在以下语法摘要中:
  • path 元素是属性的文档路径。属性必须为数字或集数据类型。
  • value 元素是要与属性相加的值(对于数字数据类型),或者是要附加到属性中的集(对于集类型)。
add-action ::=
    path value
以下是使用 add 操作的一些更新表达式示例。
以下示例对数字进行加运算。表达式属性值 :n 是数字,此值将与 Price 相加。
ADD Price :n
以下示例将一个或多个值添加到 Color 集。表达式属性值 :c 是字符串集。
ADD Color :c
DELETE
DELETE 操作只支持集数据类型。
在更新表达式中使用 DELETE 操作可从集中删除元素。要执行多个 DELETE 操作,请使用逗号分隔。
在以下语法摘要中:
  • path 元素是属性的文档路径。该属性必须是集数据类型。
  • value 元素是集中要删除的元素。
delete-action ::=
    path value
以下示例使用 DELETE 操作从 Color 集中删除元素。表达式属性值 :c 是字符串集。
DELETE Color :c

UpdateItem 示例如下:

{
    TableName: "Music",
    Key: {
        "Artist":"No One You Know",
        "SongTitle":"Call Me Today"
    },
    UpdateExpression: "SET RecordLabel = :label",
    ExpressionAttributeValues: {
        ":label": "Global Records"
    }
}
  • UpdateItem必须指定要修改的项目的 Key 属性和一个用于指定属性值的 UpdateExpression。
  • UpdateItem 替换整个项目,而不是替换单个属性。
  • UpdateItem 的行为与“upsert”操作的行为类似:如果项目位于表中,则更新项目,否则添加(插入)新项目。
  • UpdateItem只能修改单个项目,如果要修改多个项目,则必须使用多个 UpdateItem 操作。
  • UpdateItem 支持条件写入,在此情况下,操作仅在特定 ConditionExpression 的计算结果为 true 时成功完成。例如,除非歌曲的价格大于或等于 2.00,否则以下 UpdateItem 操作不会执行更新:

条件写入

要执行条件更新,请使用更新表达式以及条件表达式来执行 UpdateItem 操作。要继续执行操作,条件表达式的求值结果必须为 true;否则操作将失败。
假设您要将某项目的价格提高一定金额,如 :amt,但前提是结果不得超过最高价。为此,您可以计算当前允许提价的最高价,然后从最高价中减去提高的金额 :amt。将结果定义为 :limit,然后使用以下条件表达式:
条件表达式:Price <= :limit)
更新表达式:SET Price = Price + :amt
现在假设您要为项目设置前视图图片,不过前提是该项目还没有任何图片,不希望覆盖任何现有元素。您可以使用以下表达式来执行操作:
更新表达式:SET Pictures.FrontView = :myUR
(假设 :myURL 是项目图片的位置,例如 http://example.com/picture.jpg。)
条件表达式:attribute_not_exists(Pictures.FrontView)
{
    TableName: "Music",
    Key: {
        "Artist":"No One You Know",
        "SongTitle":"Call Me Today"
    },
    UpdateExpression: "SET RecordLabel = :label",
    ConditionExpression: "Price >= :p",
    ExpressionAttributeValues: {
        ":label": "Global Records",
        ":p": 2.00
    }
}
  • UpdateItem 还支持原子计数器或类型为 Number 的属性(可递增或递减)。原子计数器在很多方面都类似于 SQL 数据库中的顺序生成器、身份列或自递增字段。
以下是一个 UpdateItem 操作的示例,它初始化一个新属性 (Plays) 来跟踪歌曲的已播放次数:
{
    TableName: "Music",
    Key: {
        "Artist":"No One You Know",
        "SongTitle":"Call Me Today"
    },
    UpdateExpression: "SET Plays = :val",
    ExpressionAttributeValues: {
        ":val": 0
    },
    ReturnValues: "UPDATED_NEW"
}
ReturnValues 参数设置为 UPDATED_NEW,这将返回已更新的任何属性的新值。在此示例中,它返回 0(零)。
当某人播放此歌曲时,可使用以下 UpdateItem 操作来将 Plays 增加 1:
{
    TableName: "Music",
    Key: {
        "Artist":"No One You Know",
        "SongTitle":"Call Me Today"
    },
    UpdateExpression: "SET Plays = Plays + :incr",
    ExpressionAttributeValues: {
        ":incr": 1
    },
    ReturnValues: "UPDATED_NEW"
}

总结一下

  • UpdateItem 一次只能更新一个项目
  • UpdateItem 更新更新整个项目而不是只修改特点的值
  • UpdateItem 支持条件写入
这一节我们介绍了DynamoDB 项目的更新操作,下一节我们将介绍项目的删除操作(索引的查询又要延后了。。

from : https://segmentfault.com/a/1190000008707560