問題描述
我正在嘗試根據兩個不同列的組合使表中的項目保持唯一.
I'm trying to keep items in my table unique based on a combination of two different columns.
我有一個 instanceId 和 imageId 列(以及其他列)并基于 Stackoverflow 上的幾篇帖子 和 AWS 論壇 以下應該可以嗎?
I have an instanceId and imageId column (along with others) and based on a couple of posts on Stackoverflow and AWS Forums the below should work?
public void saveUnique(Server server) {
DynamoDBSaveExpression saveExpression = new DynamoDBSaveExpression();
Map<String, ExpectedAttributeValue> expectedAttributes =
ImmutableMap.<String, ExpectedAttributeValue>builder()
.put("instanceId", new ExpectedAttributeValue(false))
.put("imageId", new ExpectedAttributeValue(false))
.build();
saveExpression.setExpected(expectedAttributes);
saveExpression.setConditionalOperator(ConditionalOperator.AND);
try {
mapper.save(server, saveExpression);
} catch (ConditionalCheckFailedException e) {
//Handle conditional check
}
}
但是,每次我嘗試保存重復項(相同的 instanceId 和 imageId)時,它都會成功保存到數據庫中.
However every time I try and save a duplicate item (same instanceId and imageId) it's successfully being saved into the database.
我還有什么遺漏嗎?
編輯 R.E notionquest 答案
更新到下面的答案.
我有一項工作,每分鐘運行一次,輪詢 API.API 的響應表示為 Server
POJO.Server
有一個名為instanceId
的屬性.
I have a job that runs once a minute polling an API. The response from the API is represented as a Server
POJO. The Server
has an attribute named instanceId
.
我想確保如果具有該 instanceId
的 Server
已經在數據庫中,請不要保存它.
I want to make sure that if a Server
with that instanceId
is already in the database, don't save it.
Server
對象還有一個id
屬性,它被設置為表的主鍵.
The Server
object has another attribute of id
which is set as the table primary key.
public void saveUnique(Server server) {
DynamoDBSaveExpression saveExpression = new DynamoDBSaveExpression();
Map<String, ExpectedAttributeValue> expected = new HashMap<>();
expected.put("instanceId", new ExpectedAttributeValue(new AttributeValue(server.getInstanceId())).withComparisonOperator(ComparisonOperator.NE));
saveExpression.setExpected(expected);
try {
mapper.save(server, saveExpression);
} catch (ConditionalCheckFailedException e) {
LOGGER.info("Skipped saving as not unique...");
}
}
此代碼將一遍又一遍地保存 Server 對象,而不會引發異常.
This code will save the Server object over and over again with the exception never being thrown.
服務器 POJO
@DynamoDBTable(tableName = "Servers")
public class Server {
@Id
private String id = UUID.randomUUID().toString();
@DynamoDBTypeConvertedJson
private Task task;
@DynamoDBAttribute(attributeName = "instanceId")
private String instanceId;
public Server() {
}
@DynamoDBHashKey
public String getId() {
return id;
}
// other standard getters and setters
}
推薦答案
2019更新
在 2019 年,自提出問題以來,這里似乎沒有任何變化.在 DynamoDB 中為非主鍵字段提供唯一性仍然很棘手.這是最近在亞馬遜上發布的一篇文章:https://aws.amazon.com/blogs/database/simulating-amazon-dynamodb-unique-constraints-using-transactions/
基本上,作者建議在同一個表中創建輔助記錄,而不是使用如下所述的附加表.
Basically, instead of using an additional table as described below, the author proposes creating auxiliary records in the same table.
例如,在下圖中,為確保 instance_id=2c5d0cc8d900 是唯一值,您必須添加具有人工主鍵值instance_id#2c5d0cc8d900"的記錄.如果插入成功,您可以插入主記錄本身.
For example, on the below picture, for ensuring that instance_id=2c5d0cc8d900 is a unique value, you have to add a record with an artificial primary key value "instance_id#2c5d0cc8d900". If the insert succeeds, you can insert the main record itself.
+--------------------------+-------------------------+--------+----------------
| id | instance_id | attr1 | other fields...
| | | |
| (primary key) | (a non-key field, | |
| | must be unique) | |
+--------------------------+-------------------------+--------+----------------
| instance_id#2c5d0cc8d900 | | |
| a9fd702a | 2c5d0cc8d900 | qwerty | ...
雖然這種方法可能效果很好,但我個人仍然更喜歡使用單獨的表格,如下面的原始答案所述.因為,當從包含此類輔助記錄的表中讀取數據時,您必須注意從實際記錄中過濾它們.
While this approach may work fine, I personally still prefer to use a separate table like described below in my original answer. Because, when reading data from a table that contains such auxiliary records, you have to care about filtering them from actual ones.
如果我正確理解了這個問題,您希望確保不是哈希鍵的字段的唯一性.
If I correctly understood the question, you'd like to ensure uniqueness for a field which is not the hash key.
(我不知道你為什么不使用 instanceId
作為 Servers 表的哈希鍵,我猜你是有原因的).
(I'm not sure why you do not use instanceId
as the hash key for Servers table, I guess you have a reason for that).
我的回答:看起來如果不使用輔助表就無法做到這一點.
這是您現有的服務器表:
Here is your existing Servers table:
+----------------------------------------------+
| Servers |
+----------------------------------------------+
| * id the hash key |
| * instanceId non-key field, must be unique|
| |
| * ... |
| * other fields |
| * ... |
+----------------------------------------------+
我會創建一個帶有 instanceId 作為哈希鍵的附加表:
I would create an additional table with instanceId as the hash key:
+----------------------------------------------+
| Instance |
+----------------------------------------------+
| * instanceId the hash key |
+----------------------------------------------+
有了這樣的表,在將記錄保存到服務器之前,您必須首先確保 instanceId 值是唯一的,方法是向 Instance 添加一條記錄 (putItem),提供類似 attribute_not_exists(instanceId)
的 ConditionExpression.
Having such a table, before saving a record into Servers, you have to
ensure first that instanceId value is unique by adding a record (putItem) into Instance, providing a ConditionExpression like attribute_not_exists(instanceId)
.
只有當 put 操作完成且沒有出現 ConditionalCheckFailedException
錯誤時,您才能繼續將記錄添加到服務器中.
And only if the put operation completes without an ConditionalCheckFailedException
error, you can proceed with adding the record into Servers.
如果您想根據 instanceId 和 imageId 這兩個字段的組合來確保服務器中記錄的唯一性,而不是 instanceId 使用這些字段的連接值作為輔助表中的單個字段:
If you'd like to ensure uniqueness of records in Servers based on combination of two fields, instanceId and imageId, instead of just instanceId use concatenated values of these fields as a single field in your aux table:
+----------------------------------------------+
| Instance_Image |
+----------------------------------------------+
| * instanceId_imageId the hash key |
+----------------------------------------------+
這篇關于DynamoDBMapper 僅在唯一時保存項目的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!