DynamoDBMapper сохранить элемент, только если он уникален

Я пытаюсь сохранить элементы в своей таблице уникальными, основываясь на комбинации двух разных столбцов.

У меня есть столбец instanceId и imageId (вместе с другими), основанный на нескольких сообщениях на Stackoverflow и Форумы AWS ниже должно работать?

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), он успешно сохраняется в базе данных.

Я что-то здесь пропускаю?

РЕДАКТИРОВАТЬ R.E notionquest answer

Обновление до ответа ниже.

У меня есть работа, которая запускается раз в минуту, опрашивая API. Ответ от API представлен в виде Server POJO. Server имеет атрибут с именем instanceId.

Я хочу убедиться, что если Server с этим instanceId уже есть в базе данных, не сохраняйте его.

Объект Server имеет еще один атрибут id который устанавливается как первичный ключ таблицы.

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...");
    }
}

Этот код будет снова и снова сохранять объект «Сервер», за исключением того, что исключение не выдается.

Сервер 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
}
7 голосов | спросил Chris Turner 16 MaramThu, 16 Mar 2017 04:08:06 +03002017-03-16T04:08:06+03:0004 2017, 04:08:06

2 ответа


0

Если я правильно понял вопрос, вы хотели бы обеспечить уникальность поля, которое не является хеш-ключом.

(я не уверен, почему вы не используете instanceId в качестве хеш-ключа для таблицы серверов, я думаю, у вас есть причина для этого).

Мой ответ: похоже, что этого нельзя сделать без использования вспомогательной таблицы .

Вот ваша существующая таблица серверов:

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

Я бы создал дополнительную таблицу с instanceId в качестве хеш-ключа:

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

Имея такую ​​таблицу, перед сохранением записи на серверах необходимо Сначала убедитесь, что значение instanceId уникально, добавив запись (putItem) в Instance, предоставив выражение ConditionExp, например attribute_not_exists(instanceId)

И только если операция put завершается без ошибки ConditionalCheckFailedException, вы можете продолжить добавление записи на серверы.

Если вы хотите обеспечить уникальность записей на серверах на основе комбинации двух полей, instanceId и imageId, вместо экземпляра instanceId используйте объединенные значения этих полей как отдельное поле в вашей вспомогательной таблице:

+----------------------------------------------+
|               Instance_Image                 |   
+----------------------------------------------+
| * instanceId_imageId   the hash key          |
+----------------------------------------------+
ответил xtx 23 MarpmThu, 23 Mar 2017 13:36:05 +03002017-03-23T13:36:05+03:0001 2017, 13:36:05
0

Приведенный ниже код проверяет, является ли значение атрибута НЕ равно значению «somevalue», и обновляет элемент, если условие удовлетворяется.

Map<String, ExpectedAttributeValue> expected = new HashMap<>();     
expected.put("yourattribute", new ExpectedAttributeValue(new AttributeValue("yourvalue")).withComparisonOperator(ComparisonOperator.NE));
ответил notionquest 16 MarpmThu, 16 Mar 2017 21:38:26 +03002017-03-16T21:38:26+03:0009 2017, 21:38:26

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132