【问题标题】:How to insert HashMap into PostgreSQL as JSON type?如何将 HashMap 作为 JSON 类型插入 PostgreSQL?
【发布时间】:2020-05-09 15:36:27
【问题描述】:

contacts 的数据结构为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(())
}

我得到了提示

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

我不知道如何在这里申请pub struct Json&lt;T&gt;(pub T);

如何构建函数execute所需的query

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

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

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(())
}

我明白了

error[E0432]: unresolved import `postgres::types::Json`

【问题讨论】:

标签: postgresql rust


【解决方案1】:

你想要 Rust raw string literal:

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

在开头r#" 和结尾"# 之间,您的字符串文字可以包含除# 本身之外的任何字符而无需转义。如果您还想要 # 本身,则以多个 #s 开始原始字符串文字,并以匹配数量的 #s 结束。

【讨论】:

    【解决方案2】:

    这里是main.rs

    use postgres::{Client, NoTls};
    use serde::{Deserialize, Serialize};
    use postgres_types::Json;
    use postgres_types::{FromSql};
    
    
    #[derive(Debug, Deserialize, Serialize, FromSql)]
    struct Relation {
        name : String,
        hobby: Vec<String>
    }
    
    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 = Relation {
            name: "czfzdxx".to_string(),
            hobby: vec![
                "basketball".to_string(),
                "jogging".to_string()
            ],
        };
    
        client.execute(
            "INSERT INTO following_relation (relation) VALUES ($1)",
            &[&Json::<Relation>(rel)]
        )?;
    
        for row in &client.query("SELECT relation FROM following_relation", &[]).unwrap() {
            let rel: Json<Relation> = row.get(0);
            println!("{:?}", rel);
        }
    
        Ok(())
    }
    

    Cargo.toml:

    [package]
    name = "testapp"
    version = "0.1.0"
    edition = "2018"
    
    # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
    
    [dependencies]
    postgres = {version = "0.17.0"}
    tokio-postgres = "0.5.1"
    serde = {version = "1.0.104", features = ["derive"]}
    postgres-types = {version = "0.1.0", features = ["derive", "with-serde_json-1"]}
    serde_json = "1.0.45"
    

    这里是使用的相关文档:postgres_typespostgres。搜索 serde_jsonToSqlFromSql 特征是为此第三方类型实现的。

    【讨论】:

    • 能否添加解析client.query("SELECT relation FROM following_relation", &amp;[])?结果的代码
    • 令人惊讶的是,它并不是直截了当的。我找到了this
    • 尝试使用 serde_json::Value 代替来自 postgres 的 Json。
    • 我刚刚编辑了代码。看看它是否适合你。复制粘贴整个内容,因为我也更改了类型名称以删除警告。
    • @ComplicatedPhenomenon 不好意思说晚上看一下,我忘了。
    猜你喜欢
    • 2023-03-16
    • 1970-01-01
    • 2019-11-20
    • 1970-01-01
    • 2021-05-22
    • 2022-08-19
    • 2019-06-07
    • 2021-04-22
    • 1970-01-01
    相关资源
    最近更新 更多