DynamoDBMapper save item only if unique

2019 update

In 2019, looks like nothing has changed here since the time when the question was asked. Providing uniqueness for a non-primary-key field is still tricky in DynamoDB. Here is an article posted on Amazon recently: 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.

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.


Original answer

If I correctly understood the question, you'd like to ensure uniqueness for a field which is not the hash key.

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

My answer: looks like you can't do that without using an auxiliary table.

Here is your existing Servers table:

+----------------------------------------------+
|                 Servers                      |   
+----------------------------------------------+
| * id            the hash key                 |
| * instanceId    non-key field, must be unique|
|                                              |
| * ...                                        |
| * other fields                               |
| * ...                                        | 
+----------------------------------------------+

I would create an additional table with instanceId as the hash key:

+----------------------------------------------+
|                 Instance                     |   
+----------------------------------------------+
| * instanceId    the hash key                 |
+----------------------------------------------+

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).

And only if the put operation completes without an ConditionalCheckFailedException error, you can proceed with adding the record into Servers.

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          |
+----------------------------------------------+