如何将 HashMap 作为 JSON 类型插入 PostgreSQL?

Com*_*non 2 postgresql rust

contacts有一个数据结构 as HashMap,我使用PostgreSQL客户端 - rust-postgrescontact的键和值插入表中,然后我想从表中进行选择。以下是我到目前为止所尝试的。我需要帮助编写正确的语法。

use postgres::{Client, NoTls};
use std::collections::HashMap;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = Client::connect("host=127.0.0.1 user=postgres", NoTls)?;

    client.simple_query("
        DROP TABLE 
        IF EXISTS following_relation;
        ")?;

    client.simple_query("
        CREATE TABLE following_relation (
            id               SERIAL NOT NULL PRIMARY KEY,
            relation         JSON NOT NULL
        )
    ")?;

    let mut contacts = HashMap::new();
    let mut v: Vec<String> = Vec::new();

    v = vec!["jump".to_owned(), "jog".to_string()];
    contacts.insert("Ashley", v.clone());

    for (name, hobby) in contacts.iter() {
        // 1. How to write sql statement with parameters?
        client.execute(
        "INSERT INTO following_relation(relation) 
         VALUE ('{"name" : $1, "hobby" : $2}')", 
        &[&name, &hobby],
    )?;  
    }

    for row in client.query("SELECT id, relation FROM following_relation", &[])? {
        // 2. How to read from parse the result?
        let id: i32 = row.get(0);
        let relation = row.get(1);
        //println!("found person: {} {} {:?}", id, relation["name"], relation["hobby"]); 
    }
    Ok(())
}
Run Code Online (Sandbox Code Playgroud)

我得到了提示

  1. 就像错误消息所说的那样,您的查询具有 VALUE,但必须是 VALUES。
  2. 查询参数不能插入到字符串中。您应该在 Rust 中构建对象,并在插入时使用https://docs.rs/postgres/0.17.0/postgres/types/struct.Json.html来包装类型。

我不知道如何在pub struct Json<T>(pub T);这里申请。

如何构建query所需的功能execute

pub fn execute<T: ?Sized>(
    &mut self,
    query: &T,
    params: &[&(dyn ToSql + Sync)]
) -> Result<u64, Error>
where
    T: ToStatement, 
Run Code Online (Sandbox Code Playgroud)

更新,我尝试使用更简短的代码示例

use postgres::{Client, NoTls};
use postgres::types::Json;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
struct relations {
    name : String,
    hobby: Vec<String>
}
pub struct Json<T>(pub T);

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = Client::connect("host=127.0.0.1 user=postgres", NoTls)?;

    client.simple_query("
        DROP TABLE 
        IF EXISTS following_relation;

        ")?;

    client.simple_query("
        CREATE TABLE following_relation (
            id      SERIAL PRIMARY KEY,
            relation    JSON NOT NULL
        )
    ")?;

    let rel = relations {
        name: "czfzdxx".to_string(),
        hobby: vec![
            "basketball".to_string(),
            "jogging".to_string()
        ],
    };

    client.execute(
        r#"INSERT INTO following_relation(relation)
             VALUE ($1)"#,
        &[&Json(&rel)]
    )?;

    Ok(())
}
Run Code Online (Sandbox Code Playgroud)

我得到

error[E0432]: unresolved import `postgres::types::Json`
Run Code Online (Sandbox Code Playgroud)

edw*_*rdw 5

你想要 Rust原始字符串文字

for (name, hobby) in contacts.iter() {
    client.execute(
        r#"INSERT INTO following_relation(relation) 
           VALUE ('{"name" : ($1), "hobby" : ($2)}')"#,
        &[&name, &following],
    )?;
}
Run Code Online (Sandbox Code Playgroud)

在 startr#"和 end 之间"#,您的字符串文字可以包含除#自身之外的任何字符而无需转义。如果你也想要#它自己,那么以多个#s开始原始字符串文字,并以匹配数量的#s结束。