简体   繁体   English

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

[英]How to insert HashMap into PostgreSQL as JSON type?

contacts has a data structure as HashMap , I'm using PostgreSQL client - rust-postgres to insert contact 's key and value into a table, then I want to select from the table. contacts的数据结构为HashMap ,我使用PostgreSQL客户端 - rust-postgrescontact的键和值插入表中,然后我想从表中进行选择。 Below is what I tried so far.以下是我到目前为止所尝试的。 I need help with writing the right syntax.我需要帮助编写正确的语法。

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

I've been given the hints我得到了提示

  1. Like the error message says, your query has VALUE but it needs to be VALUES.就像错误消息所说的那样,您的查询具有 VALUE,但必须是 VALUES。
  2. Query parameters cannot be interpolated into strings.查询参数不能插入到字符串中。 You should build the object in Rust, and usehttps://docs.rs/postgres/0.17.0/postgres/types/struct.Json.html to wrap the types when inserting.您应该在 Rust 中构建对象,并在插入时使用https://docs.rs/postgres/0.17.0/postgres/types/struct.Json.html来包装类型。

I have no idea how to apply pub struct Json<T>(pub T);我不知道如何应用pub struct Json<T>(pub T); here.这里。

How to build the query required in function execute ?如何构建函数execute所需的query

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

UPDATED, I tried with a more brief code sample更新,我尝试使用更简短的代码示例

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

I get我得到

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

You want Rust raw string literal :你想要 Rust 原始字符串文字

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

Between the start r#" and the end "# , your string literals can have any character except # itself without escaping.在开始r#"和结束"# ,您的字符串文字可以包含除#本身之外的任何字符而无需转义。 If you also want # itself, then starts the raw string literals with multiple # s and ends with matching number of # s.如果您还想要#本身,则以多个#开始原始字符串文字,并以匹配数量的#结束。

Here is main.rs :这是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(())
}

and Cargo.toml :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"

And here is the relevant documentation used: postgres_types and postgres .这是使用的相关文档: postgres_typespostgres Search for serde_json , ToSql and FromSql traits are implemented for this third-party type.搜索serde_jsonToSqlFromSql特征是为此第三方类型实现的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM