0
votes

I am working on a bookmark skill for Alexa to teach myself DynamoDB. I've got over various hurdles, and can now write to my table. The issue is that whenever I putItem it adds two items. I'm trying to store the userID (partition key in DynamoDB), the timestamp of the request (as a string, and the sort key in DynamoDB), the title of a book and the page the user is on. This issue has only started since I tried working with a composite key, but I think I will need both these fields to a) get a unique primary key and b) be able to find the last item saved by a user.

Here's my intent code in Lambda:

'addBookmark': function() {

        //delegate to Alexa to collect all the required slot values
        var filledSlots = delegateSlotCollection.call(this);

        //Get slot values as variables
        var userID = this.event.session.user.userId;
        var pageNumber = this.event.request.intent.slots.pageNumber.value;
        var bookTitle = this.event.request.intent.slots.bookTitle.value;

        //DynamoDB expects the timestamp as a string, so we convert it
        var timeStamp = Date.now().toString();

        var params = {
            TableName: 'bookmarkV6',
            Item: {
                'userID'    : {S: userID},
                'timeStamp': { S: timeStamp },
                'bookTitle': { S: bookTitle },
                'pageNumber': { N: pageNumber },
                }
        };

        //Call DynamoDB to add the item to the table
        ddb.putItem(params, function(err, data) {
            if (err) {
                console.log("Error", err);
            }
            else {
                console.log("Success", data);
            }
        });

        const speechOutput = "OK, I've made a note that you're on page " + pageNumber + " of " + bookTitle + ".";
        this.response.cardRenderer("Bookmark", "Page " + pageNumber + " of " + sentenceCase(bookTitle) +"\n \n" + stringToDate(timeStamp));
        this.response.speak(speechOutput);
        this.emit(':responseReady');

    },

The "duplicate" items have slightly different timestamp values.

2
I would debug to verify how many times addBookmark is called. If you're sure it's only called once, then I'd look at the table stream. Maybe you've got a stream consumer duplicating the entry each time?gerrytan
Thanks for responding. I've got no idea how to debug that... Would it be somewhere in the logs?Notsofastmatey
OK, I couldn't find the logs in Cloudwatch, but in the end I created a test event by copying the input JSON from the Alexa Skills kit. That gave me a "normal" Lambda log beneath my function. It seems to only fire once. However, I tried removing the var filledSlots = delegateSlotCollection.call(this); line and that solved the duplicate items issue. My guess is that I've somehow implemented that incorrectly and it is going back to look for missing slots even though they are all filled, so the dynamoDB putItem is running twice.Notsofastmatey

2 Answers

0
votes

I am also having the same issues. It is happening of delegate collections used, but not able to solve. I have delegate slot confirmation for 6 slots and when I give all 6 slots value, finally I end up with 7 records in the table.

0
votes

In delegateSlotCollection() function, return "COMPLETED" in the else block and in your addbookmark intent , please check like below after your delegateSlotCollection.call method

var filledSlots = delegateSlotCollection.call(this); if(filledSlots==='COMPLETED'){ place all your save dynamodb logic here. }