title: Not Expected Results in DynamoDB PutItem
body: <p><strong>Q: How can I avoid inserting an item into a table, when I have a composite primary key?</strong></p>
  
  <p>I could only find examples in the documentation with a single primary key (only a partition key, but not with a partition key AND a sorting key).</p>
  
  <p><strong>Context:</strong> </p>
  
  <ul>
  <li>My partition key is named PK and the sorting is named SK.</li>
  <li>My PK is a UUID, SK is composed of a random bucket [0-9] e.g., "user#info#3", (3 is the random bucket).</li>
  <li>The same PK may appear multiple times, but SK for each of those repetitions will always be different.</li>
  <li>I want to insert the item in the table only when (PK is non-existent) OR (PK is existent AND SK doesn't begin with user#info)</li>
  </ul>
  
  <p><strong>What I expect vs my outcome</strong> </p>
  
  <ul>
  <li><code>[outcome: expected - the item was not inserted]</code> If I try to insert an item with an existent PK, and exact SK (e.g., inserting user#info#3, and user#info#3 already exists), the item should NOT be inserted.</li>
  <li><code>[outcome: NOT expected - the item was inserted]</code> If I try to insert an item with an existent PK, and non-exact SK (e.g., inserting user#info#3, and user#info#5 already exists), the item should NOT be inserted.</li>
  <li><code>[outcome: expected - the item was inserted]</code> If I try to insert an item with a non-existent PK, the item should be inserted.</li>
  </ul>
  
  <p>I'm using this command line snippet (modified from <a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ConditionExpressions.html" rel="nofollow noreferrer">here</a>) to insert data into the table:</p>
  
  <pre><code>aws dynamodb put-item \
      --table-name Users \
      --item file://item.json \
      --condition-expression "attribute_not_exists(PK) OR NOT begins_with(SK, :sk)" \
      --expression-attribute-values file://values.json
  </code></pre>
  
  <p>item.json</p>
  
  <pre><code>{
      "PK": {
          "S": "910cc6dd-b7e2-4286-89d4-db3d0e3fde6b"
      },
      "SK": {
          "S": "user#info#4"
      },
      "Name": {
          "S": "Greg"
      }
  }
  </code></pre>
  
  <p>values.json</p>
  
  <pre><code>{
      ":sk": {
          "S": "user#info"
      }
  }
  </code></pre>
  
  <p>If I remove the PK condition, and try to check only against the SK condition, it inserts the item (I'd expect it to NOT insert the item), e.g.:</p>
  
  <pre><code>aws dynamodb put-item \
      --table-name Users \
      --item file://item.json \
      --condition-expression "NOT begins_with(SK, :sk)" \
      --expression-attribute-values file://values.json
  </code></pre>
  
  <p>The above inserts the item, even though there is another item in the table that begins with <code>user#info</code></p>