AWS之Amazon DynamoDB用法详解

2022-04-08 00:00:00 字段 更新 项目 主键 表达式

AWS入门之Amazon DynamoDB的快速入门(一)
说明
什么是DynamoDB?
DynamoDB核心组件
使用DDB前的一些配置
DynamoDB的create
1.newItem添加记录
2.根据mapper映射添加
DynamoDB的update
1.根据spec更新项目
2.根据spec有条件更新Item
DynamoDB的retrieve
1. 根据主键读取项目
2.根据spec读取项目
DynamoDB的delete
1.根据主键删除项目
2.根据spec删除项目
附:Item 的一些方法调用
说明
近公司开始用aws的一些服务了,因此有必要学习一下aws的一些知识。但aws的开发文档貌似对新手不太友好的样子,而网上的知识又太多太杂,筛选知识需耗费一定时间,且照着文档敲完,过段时间又会忘记。因此,有必要总结一下一些关于DDB的操作,以便自己实时的学习,也希望自己写的blog能够帮助到别人。

什么是DynamoDB?
Amazon DynamoDB 是一种完全托管的 NoSQL 数据库服务,提供快速且可预测的性能,同时还能够实现无缝扩展。同时,DynamoDB 会自动将您的表的数据和流量分散到足够数量的服务器上,以满足您的吞吐量和存储需求,同时保持始终如一的高性能。
  简单来说,DDB就是AWS提供的一个NoSql数据库。

DynamoDB核心组件
表 Table:和其他类型的数据库差不多,相当于所有数据的集合。
项目 Item:每一条Item就是表中的一条数据。
主键 PriamryKey:
分区键,创建表时必须要有的字段,用来确定表中数据的性。
排序键,创建表时可选可不选,可理解为二级主键 。当两条项目有相同的分区键时,必须要有不同的排序键区分它们。
属性 Attributes:项目的字段名,如user中,name,gender,age为字段名。
使用DDB前的一些配置
1.首先需要有aws的账户,接着获取访问密钥,配置凭证等等。个人可以注册国外账户,国内目前好像只有企业用户才能申请。设置DynamoDB

2.控制台创建一张user表用作示例

user_id date age name gender hobby
12345 2019-01-05 20 Sakura 1 [ { “type” : “sing”}, {“type” : “walk”} ]

3.接着开始代码,先是maven的导入

<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-dynamodb</artifactId>
<version>1.11.683</version>
</dependency>

4.自己写的DBUtils

public class DBUtils {

static String endPoint = "endpoint";
static String region = "region";
static String tableName = "tableName";

public static AmazonDynamoDB getClient() {
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()
.withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(endPoint, region))
.build();
return client;
}

//后面主要table用的多
public static Table getTable() {
AmazonDynamoDB client = getClient();
DynamoDB dynamoDB = new DynamoDB(client);
return dynamoDB.getTable(tableName);
}
}

DynamoDB的create
1.newItem添加记录
public void createItem() {
String userId = "123456";
String date = "2020-01-05";
String name = "Sakura";
String age = "20";
String gender = "1";
List<Map> hobby = new ArrayList<>();
Map<String, String> map1 = new HashMap<>();
Map<String, String> map2 = new HashMap<>();
map1.put("type", "sing");
map2.put("type", "walk");
hobby.add(map1);
hobby.add(map2);

Item item = new Item().withPrimaryKey("user_id", userId,"date",date)
.withString("name", name)
.withString("age", age)
.withString("gender", gender).withList("hobby",hobby);

table.putItem(item);
}

2.根据mapper映射添加
@Data、@AllArgsConstructor、@NoArgsConstructor为Lombok插件带的注解。
@DynamoDBTable注解值为表名,@DynamoDBHashKey为主键,@DynamoDBAttribute为字段属性。

public void createItemByMapper(){
List<Map> hobby = new ArrayList<>();
User user = new User("12345", "2020-01-05", "Sakura", "20", "1", hobby);

AmazonDynamoDB client = DBUtils.getClient();
DynamoDBMapper mapper = new DynamoDBMapper(client);

mapper.save(user);
}

DynamoDB的update
1.根据spec更新项目
UpdateExpression为更新表达式,一般格式为 set #字段名 = :修改值,具体好像是因为aws存有一些保留字会冲突啥的,因此用#代表占位符,所以更新表达式中需用变量替换表中的字段名。
  NameMap为更新表达式中你所表示的字段的名称,如示例中,#name代表的就是表中name这个字段。
  ValueMap为更新表达式中你所要更新的值,如:val的值为nameVal,冒号(:)也代表占位符,就表示将表中name这个字段的值改为nameVal。
  后ReturnValues为枚举类,有NONE,ALL_OLD,UPDATED_OLD,ALL_NEW,UPDATED_NEW五个,具体啥区别我目前也还没弄清,知道的望评论help me解惑一下,谢谢!

public void updateItemBySpec() {
String userId = "12345";
String date = "2020-01-05";

//要修改的值
String nameVal = "Jack";
List<Map> hobby = new ArrayList<>();

UpdateItemSpec updateItemSpec = new UpdateItemSpec().withPrimaryKey("user_id", userId, "date", date)
.withUpdateExpression("set #name = :val1 , #hobby = :hobby")
.withNameMap(new NameMap().with("#name", "name").with("#hobby", "hobby"))
.withValueMap(new ValueMap().with(":val1", nameVal).withList(":hobby", hobby))
.withReturnValues(ReturnValue.UPDATED_NEW);

table.updateItem(updateItemSpec);
}

2.根据spec有条件更新Item
如下示例中,当hoby的数量小于10时,将name的值(Sakura)改为Tony,具体条件表达式写在ConditionExpression中。

public void updateItemBySpecCondition() {
String userId = "123456";
String date = "2020-01-05";
//要更新的值
String nameVal = "Tony";

UpdateItemSpec spec = new UpdateItemSpec().withPrimaryKey("user_id", userId, "date", date)
.withUpdateExpression("set #name = :val1")
.withConditionExpression("size(hobby) < :num")
.withNameMap(new NameMap().with("#name", "name"))
.withValueMap(new ValueMap().with(":val1", nameVal).withNumber(":num", 10))
.withReturnValues(ReturnValue.UPDATED_NEW);

table.updateItem(spec);
}

具体的比较运算符和函数可参考官方文档:awsDynamoDB官方文档
DynamoDB的retrieve
1. 根据主键读取项目
其中,user_id为该表分区键,date为排序键(如果有的话),name、age、gender为该表的字段。
需要查询哪些字段,可直接在getItem后用逗号拼上需查询的字段名。

public void retrieveItemByPrimaryKey() {
String userId = "12345";
Item item = table.getItem("user_id", userId, "name,age,gender", null);
//如果该表有排序键时需改为:
//Item item = table.getItem("user_id", userId, "date", date,"name,age,gender",null);
}

2.根据spec读取项目
public void retrieveItemBySpec(){
String userId = "12345";
String date = "2020-01-05";

GetItemSpec getItemSpec = new GetItemSpec()
.withPrimaryKey("user_id", userId, "date", date)
.withAttributesToGet("name", "gender", "age");

Item item = table.getItem(getItemSpec);
}

DynamoDB的delete
删除一般用的比较少,慎用,一不小心就可能要跑路的样子。

1.根据主键删除项目
public void deleteItemByPrimaryKey() {
String userId = "12345";
String date = "2020-01-05";

table.deleteItem("user_id", userId, "date", date);
}

2.根据spec删除项目
删除项目也可以用到表达式,示例中,当hobby的长度小于10时,删除该条记录,否则,会直接报异常
即:如果:num那改为1,hobby实际长度为2,执行此方法则会报异常信息。因此,实际使用时可能需要手动try catch。

public void deleteItemBySpec(){
String userId = "12345";
String date = "2020-01-05";

DeleteItemSpec spec = new DeleteItemSpec().withPrimaryKey("user_id", userId, "date", date)
.withConditionExpression("size(hobby) < :num")
.withValueMap(new ValueMap().with(":num", 10));

table.deleteItem(spec);
}

附:Item 的一些方法调用
一般数据传输用的都是json格式,如果Item直接输出的话,格式不是我们想要的:

System.out.println(item);

{ Item: {date=2020-01-05, gender=1, user_id=12345, name=Sakura, age=20, hobby=[{type=sing}, {type=walk}]} }

因此拿到item后还需做些转化:

item.asMap(),将item转化为map格式:
Map<String, Object> map = item.asMap();
System.out.println(map);

{date=2020-01-05, gender=1, user_id=12345, name=Sakura, age=20, hobby=[{type=sing}, {type=walk}]}

item.getList(“hobby”),获取对应的list
List<Map> hobby = item.getList("hobby");
System.out.println(hobby);

[{type=sing}, {type=walk}]

item.getJSON(“hobby”),直接获取json数据
String json = item.getJSON("hobby");
System.out.println(json);

[{"type":"sing"},{"type":"walk"}]

次写blog,可能会有许多不足之处,有些地方还没写到(如二级索引等,毕竟自己也没弄明白)欢迎大家指正。谢谢大家的阅读,有问题的话大家一起讨论,下面附awsDDB官方文档供查阅。谢谢~~~

相关文章