Thiago
Thiago

Reputation: 672

Why is DynamoDB adding a NULL suffix to attribute names?

I've been working on a toy project and noticed that dynamo added a (NULL) suffix in two of my attribute names. I had not noticed before, so I assume it must have happened after one of my code changes. I could not find any reference to this behavior online.

dynamodb null attribute name suffix

The script I'm running is a simple PutItem got from the official Dynamodb documentation, where I insert a few mock users in a table.

func InsertModel(m interface{}) error {
    av, err := dynamodbattribute.MarshalMap(m)
    if err != nil {
        return fmt.Errorf("handlers: Got error marshalling map: %v", err)
    }

    input := &dynamodb.PutItemInput{
        Item:                av,
        TableName:           aws.String(appTableName),
        ConditionExpression: aws.String("attribute_not_exists(PK) AND attribute_not_exists(SK)"),
    }

    _, err = svc.PutItem(input)
    if err != nil {
        return fmt.Errorf("handlers: Got error calling PutItem: %v", err)
    }

    return nil
}

m (user mock data) has all fields type string:

UserModel{PK: "910cc6d8-b7e2-dfg6-d8d4-sh6d0e3fde6b", SK: "user_info", Name: "bla", ImageURI: "aaa"},

When I remove the fields "Name" and "ImageURI", the PutItem inserts a boolean true to the field value as seen below.

dynamodb boolean attr value when not present in putitem

Here is the value in av after the MarshalMap operation.

  1. with populated "Name" and "ImageURI" fields:
map[ImageURI:{
  S: "aaa"
} Name:{
  S: "bla"
} PK:{
  S: "910cc6d8-b7e2-dfg6-d8d4-sh6d0e3fde6b"
} SK:{
  S: "user_info"
}]
  1. and here without "Name" and "ImageURI" as in UserModel{PK: "910cc6d8-b7e2-dfg6-d8d4-sh6d0e3fde6b", SK: "user_info"}
map[ImageURI:{
  NULL: true
} Name:{
  NULL: true
} PK:{
  S: "910cc6d8-b7e2-dfg6-d8d4-sh6d0e3fde6b"
} SK:{
  S: "user_info"
}]

I have tried to delete all the records from the table and insert again but the behavior continues. Also, I did the same process for an int type attribute (inserting the object with the int attribute populated and not populated) and I get 0 when it's not populated (which is what I'd expect). I tried replicating this with a different string type attribute, and I get the same behavior (true when empty), but the attribute name doesn't get the suffix NULL.

So in summary, it seems this behavior is mostly happening with type string in my case, and I only get a NULL suffix in the attributes "Name" and "ImageURI", but not on the other string attribute I've tried (nor the int one).

Upvotes: 2

Views: 1504

Answers (2)

Josh Hibschman
Josh Hibschman

Reputation: 3724

Option A

The dynamodbattribute.MarshalMap method reads json struct tags if present. By adding omitempty it will leave the attribute off of the item. Then when reading it back later, it will default to the empty value in the struct.

type Foo struct {
    Bar string `json:"bar,omitempty"`
}

Option B

You can explicitly set empty struct values by either creating your own dynamodb.AttributeValue or implement the marshaller interface on your struct. For example:

item := map[string]*dynamodb.AttributeValue{
  "Foo": {
    S: aws.String("")
  }
}

Making the (NULL) suffix to go away

After deleting all the rows containing a NULL value in a column with the (NULL) suffix, it seems to take some time for the suffix to go away from the AWS UI. When I tested this, it took roughly 12 hours.

Discussion

Continue the discussion of null behaviors on github.

Upvotes: 0

Marco
Marco

Reputation: 11

I had the same issue for one of the fields of my table items.
For that field I was doing an update using the NameMap option, useful when you want to use a name that, for some other reasons, is reserved by dynamo. I just tried not to use the NameMap option, giving another name for my field, and that suffix disappeared. I hope my experience could be somehow helpful. Regards

Upvotes: 1

Related Questions