amazon-web-servicesrustamazon-dynamodbaws-sdk-rust

Store HashMap in DynamoDB database with aws-sdk-rust in compact code?


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.


Solution

  • 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:

    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.