awslabs / dynamodb-data-mapper-js

A schema-based data mapper for Amazon DynamoDB.
https://awslabs.github.io/dynamodb-data-mapper-js/
Apache License 2.0
817 stars 106 forks source link

mapper update option, onMissing not working #130

Closed lockphase closed 5 years ago

lockphase commented 5 years ago

I took the example for the docs and modified it for my use case for testing using javascript.

// put something new into the database
const toPut = new User();
toPut.id = 'NEW_RECORD';
toPut.name = 'bar';
toPut.isValid = false;

mapper.put(toPut).then((persisted) => {
    // now change the record a bit
    const toUpdate = new User();
    toUpdate.id = persisted.id;
    toUpdate.name = 'bar2';
    //toUpdate.isValid = false;
    mapper.update(toUpdate, {onMissing: 'skip'}).then(info=>{
            console.log(info);
    }).catch(err=>{
            console.log(err);
    });
});

Commenting 'toUpdate.isValid = false;' throws the ValidationException error with the message: The expression can not be empty. Is the onMissing option WAI or am I missing smthg? dynamodb-data-mapper 0.7.3 version

ghost commented 5 years ago

@lockphase is your "isValid" attribute optional in your User class.

@attribute() isValid?: boolean vs @attribute() isValid: boolean

lockphase commented 5 years ago

erm, no its not set to optional. I gather onMissing only works if properties have the optional flag ? How can I set it ? I came from this link on aws: https://aws.amazon.com/blogs/developer/introducing-the-amazon-dynamodb-datamapper-for-javascript-developer-preview/ and it states that a model can be created without ts which is what I have done. Didn't see anything there about optional props. Kindly advise, thanks.

ghost commented 5 years ago

What does your User class look like? To be honest i'm struggling with this library myself a little, so not sure I can answer. The community around it isn't that strong either which makes it hard to get answers.

Have you read through the following: https://github.com/awslabs/dynamodb-data-mapper-js/tree/master/packages/dynamodb-data-marshaller#supported-types

Maybe you need an onEmpty property, but i'm guessing a bit.

jeskew commented 5 years ago

@lockphase What's the table schema for users? If both id and name are keys, the code snippet would result in an empty update expression.

lockphase commented 5 years ago

Hi guys, thanks for all the replies. I figured out what was wrong, not sure if its a bug tho. Below is my schema. As its for testing purposes, stuff are all at bare minimum.

class User {
}
Object.defineProperties(User.prototype, {
    [DynamoDbTable]: {
        value: 'Users'
    },
    [DynamoDbSchema]: {
        value: {
            id: { type: 'String', keyType: 'HASH'},
            name: { type: 'String', keyType: 'RANGE'},
            isValid: {type: 'Boolean'}
        },
    },
});

@jeskew , yes you are right. Both id and name are keys, What I did was to not declare a new User and it worked. Is this the correct way? Why should it throw empty update expression if both are keys ? My use case does involve keys being updated, should I be worried ?

mapper.put(toPut).then((persisted) => {
    // now change the record a bit
    persisted.name = 'bar2';
    mapper.update(persisted, {onMissing: 'skip'}).then(info=>{
            console.log(info);
    }).catch(err=>{
            console.log(err);
    });
});
jeskew commented 5 years ago

@lockphase My understanding is that updates must alter a non-key property of the record. Since name is the range key, you aren't updating the original record but instead creating a new one. If there are no values set for non-key attributes, a put operation should be used instead.

lockphase commented 5 years ago

@jeskew I see, ok thanks for the info. I'm closing this since onMissing is wai.