45

I am using nodeJS sdk to put the item to dynamoDB, The item is:

{
   "eventId": date + '-' + eventName + '-' + eventPurpose,
   "eventName": eventName,
   "eventPurpose": eventPurpose,
   "eventDates": eventDates,
   "attendees": attendees
 }

The present code for the putting the item in dynamoDB:

  const params = {
    TableName: "event",
    Item: {
        "eventId": date + '-' + eventName + '-' + eventPurpose,
        "eventName": eventName,
        "eventPurpose": eventPurpose,
        "eventDates": eventDates,
        "attendees": attendees
    },
    ReturnValues: "ALL_OLD"
  };

  dynamo.put(params, (err, data) => {
    console.log("coming here");
    if (err) {
      console.log("error : " + JSON.stringify(err));
    }
    console.log("data" + JSON.stringify(data));
    cb(null, data);
  });

The insertion happens correctly and the return value is an empty object.

I would like to return the inserted item. I found this doc. But this returns only in case of updating the old value. I could not find any other useful info other than this.

Is there any work around or we simply need to query using get method with the primary key?

Lakshman Diwaakar
  • 7,207
  • 6
  • 47
  • 81
  • Note in your callback if you receive `err` you should definitely not call the lambda `callback` as if it was successful. A regular `if/else` block will help remove confusion in the future! – Peter Wagener Sep 12 '16 at 22:04

4 Answers4

33

The link you posted is, sadly, the only real answer at this time (API Version 2012-08-10). PutItem may return items just before they were updated or none at all.

The ReturnValues parameter is used by several DynamoDB operations; however, PutItem does not recognize any values other than NONE or ALL_OLD.

In short, the only reliable way to retrieve your inserted object is to GetItem, just as you surmised.

Diego Ferri
  • 2,657
  • 2
  • 27
  • 35
27

Just pass the params.Item in the callback :

 dynamo.put(params, (err, data) => {
        if (err) {
          cb(err);
        }
        cb(null, params.Item);
      });

Pass the err in the callback too ;)

Sigma
  • 532
  • 3
  • 8
  • 7
    Where have you been all my life – booky99 Jun 18 '17 at 16:05
  • 19
    isn't that cheating? ... I mean I want the real data that was inserted in the db, right? – MeBNoah Oct 26 '17 at 14:04
  • Kind of. It depends on what do you want to return : the object that you want to store on the database or the actual stored object. – Sigma Oct 28 '17 at 15:31
  • 12
    The actual object stored could be slightly different than the object that you wanted to store. While passing the err should allow for a failed creation of the object, this isn’t really an answer to the question. – Harry Apr 10 '18 at 09:56
  • Aweesome hack!! – BALA Jun 11 '19 at 07:07
17

You can use UpdateItem instead of PutItem. UpdateItem creates a new item if it doesn't exist already, plus you can set ReturnValues to ALL_NEW to return the whole item as it appears in the database after the operation:

const params = {
    TableName: "event",
    Key: {
        "eventId": date + '-' + eventName + '-' + eventPurpose
    },
    UpdateExpression: "SET eventName = :eventName, eventPurpose = :eventPurpose, eventDates = :eventDates, attendees = :attendees",
    ExpressionAttributeValues: {
        ":eventName": eventName,
        ":eventPurpose": eventPurpose,
        ":eventDates": eventDates,
        ":attendees": attendees
    },
    ReturnValues: "ALL_NEW"
};

Using GetItem right after PutItem is not a good idea unless you are using strong consistency in DynamodDB. If you have eventual consistency (default) then GetItem right after PutItem can still return empty.

drsolarcat
  • 171
  • 1
  • 3
3

Note that this is the item you are inserting, which you already have access to:

{
    "eventId": date + '-' + eventName + '-' + eventPurpose,
    "eventName": eventName,
    "eventPurpose": eventPurpose,
    "eventDates": eventDates,
    "attendees": attendees
}

You could simply change your code to this, and then you would have the inserted item in the item variable already:

var item = {
        "eventId": date + '-' + eventName + '-' + eventPurpose,
        "eventName": eventName,
        "eventPurpose": eventPurpose,
        "eventDates": eventDates,
        "attendees": attendees
    };

const params = {
    TableName: "event",
    Item: item,
    ReturnValues: "ALL_OLD"
  };

You seem to be confused about what you are inserting, because you start your question by showing an object you say you are inserting, but the code you posted is inserting a slightly different object.

Mark B
  • 183,023
  • 24
  • 297
  • 295
  • 1
    ya you are correct. The first code snippet contains the request body. Somehow, I got confused and made it has object. Coming to the question, your solution is a good one but usually in mongoDB, it returns the inserted object and I thought there might be something similar in dynamoDB. **ReturnValues: "ALL_NEW"** is allowed only in update operations. In **put** operation only **NONE** or **ALL_OLD**. Thanks for the quick answer. I will follow as you said. Simple and elegant approach. Thanks mark!! – Lakshman Diwaakar Sep 12 '16 at 13:56