0

I'm new to Rust, and I'm trying to store a HashMap in a DynamoDB using aws-sdk-rust.

Here is my code, copied more or less verbatim from here but adapted to try to insert a whole Hashmap in one statement, rather than manually adding multiple .item() calls:

#[tokio::main]
async fn main() {
    if let Err(e) = write_to_dynamodb().await {
        eprintln!("Error: {}", DisplayErrorContext(e));
    }
}

async fn write_to_dynamodb() -> Result<(), Error> {
    let region_provider = RegionProviderChain::default_provider().or_else("eu-west-2");
    let config = aws_config::from_env().region(region_provider).load().await;
    let client = Client::new(&config);

    let my_map = HashMap::from([
        ( "id".to_string(), AttributeValue::S("26236236".to_string(),),),
        ( "device_name".to_string(), AttributeValue::S("foobar".to_string(),),),
        // etc
    ],);

    let request = client
        .put_item()
        .table_name("MyTable")
        .item(my_map);
    request.send().await?;

    Ok(())

}

This gives me lots of errors though, starting:

error[E0277]: the trait bound `std::string::String: From<HashMap<std::string::String, AttributeValue>>` is not satisfied
    --> src/main.rs:34:15
     |
34   |         .item(my_map);
     |          ---- ^^^^^^ the trait `From<HashMap<std::string::String, AttributeValue>>` is not implemented for `std::string::String`
     |          |
     |          required by a bound introduced by this call
     |

I guess I need to use something other than put_item, though the documentation suggests I ought to be able to add a HashMap.

How can I insert a whole HashMap directly, rather than adding one key-value pair at a time?

Confusingly the GitHub docs suggest using a whole different method: add_item rather than put_item.

Richard
  • 62,943
  • 126
  • 334
  • 542

1 Answers1

2

Indeed you are able to pass a hash map directly. If you examine the PutItemInput builder docs, you will notice there are more (convenience) functions available for us:

  • item that adds an entry to the item, and
  • set_item that sets the entire item.

So if you replace your call with

set_item(Some(my_map))

it should all work out. See modified excerpt from your own example:

let my_map = HashMap::from([
    ( "id".to_string(), AttributeValue::S("26236236".to_string(),),),
    ( "device_name".to_string(), AttributeValue::S("foobar".to_string(),),),
    ]);
let request = client
    .put_item()
    .table_name("foo")
    .set_item(Some(my_map)); // Note the set_item call.
Victor
  • 13,914
  • 19
  • 78
  • 147
  • That worked! Thank you. I wouldn't have noticed the `Some` there - still learning how to navigate the docs. – Richard Mar 15 '23 at 13:19