How to prevent creating a new item in UpdateItem if the item does not exist

I bumped into a somehow similar problem using attribute_exists, the only difference is, I need to query from the table and get only the record that does have the attribute I need. Using ConditionExpression did not work for me. Thought of sharing it here in case someone is in need.

Here, if the subscriberKey is equal to given param and the attribute_exists (mobileNumber) within the record, it returns true, false otherwise.

var params = {
    TableName : table_name,
    IndexName: "subsciberKey-index",
    KeyConditionExpression: "subscriberKey = :subscriberKey",
    FilterExpression: "attribute_exists(mobileNumber)",
    ExpressionAttributeValues: {
        ":subscriberKey": subscriberNo
    }
};

You can use ConditionExpression for this. The update will happen if the key (i.e. userId) is present and update attribute (i.e. isActive) is not equal to the new value that you are trying to update.

ConditionExpression: "userId = :userIdVal and isActive <> :isActiveVal",
ExpressionAttributeValues: {
    ':isActive': 'false',
    ':userIdVal': '123'
},

EDIT:-

This should work. It should be ConditionExpression (not ConditionalExpression).

var params = {
    TableName: 'users',
    Key: {
        'userId': '123'
    },
    UpdateExpression: 'SET isActive = :isActiveVal',
    ConditionExpression: 'userId = :userIdVal and isActive <> :isActiveVal',
    ExpressionAttributeValues: {
        ':userIdVal': '123',
        ':isActiveVal': 'false'
    },
    ReturnValues: "ALL_NEW"
};

Update, 2020:

You can use attribute_exists in ConditionExpression to check if the item exists or not. (Sources: 1, 2)

const params = {
    TableName: 'users',
    Key: {
        'userId': '123'
    },
    UpdateExpression: 'SET isActive = :isActiveVal',
    ConditionExpression: 'attribute_exists(userId)',
    ExpressionAttributeValues: {
        ':isActiveVal': 'false'
    },
    ReturnValues: "ALL_NEW"
};

ConditionExpression is the way to go, but you can also use the attribute_exists function :

ConditionExpression: 'attribute_exists(userId)'

It will only update the line with the correct key and throw a ConditionalCheckFailedException if requested key doesn't exist.

The goal is more obvious and you can skip the extra userId binding.

ref : https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html