Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AqlQuery with bind_vars #29

Closed
inzanez opened this issue Aug 11, 2020 · 6 comments
Closed

AqlQuery with bind_vars #29

inzanez opened this issue Aug 11, 2020 · 6 comments

Comments

@inzanez
Copy link
Contributor

inzanez commented Aug 11, 2020

Hi

How is one supposed to be using bind_vars? Using the web-query-builder from ArangoDB, I'm used to being able to create queries as follows:
INSERT @user INTO @@collection with user: { "name": "Test" } and @collection: "users".

Assuming I tried the same with the query builder, I tried:

const COLLECTION: &str = "users";

#[derive(Serialize)]
pub struct User {
    name: String,
}

fn main() {
    let user = User { name: "Tester".to_string() };
    let conn = Connection::establish_jwt("http://localhost:8529", "root", "Password")
        .unwrap();

    let db = conn.db("Test").unwrap();

    let json = serde_json::to_string(&user).unwrap();
    let aql = AqlQuery::builder()
        .query("INSERT @user INTO @@collection LET result = NEW RETURN result")
        .bind_var("@collection", COLLECTION)
        .bind_var("user", json)
        .build();

    let result: Vec<Value> = db.aql_query(aql).expect("Query failed");
}

However, that fails, as the query generated escapes the double quotes in the JSON that I generated. Resulting in this:
{"query":"INSERT @client INTO @@collection LET result = NEW RETURN result","bindVars":{"client":"{\"name\":\"Tester\"}","@collection":"fs_clients" }

instead of this
{"query":"INSERT @client INTO @@collection LET result = NEW RETURN result","bindVars":{"client":"{"name":"Tester"}","@collection":"fs_clients" }

If I tried assigning the user struct directly however:

const COLLECTION: &str = "users";

#[derive(Serialize)]
pub struct User {
    name: String,
}

fn main() {
    let user = User { name: "Tester".to_string() };
    let conn = Connection::establish_jwt("http://localhost:8529", "root", "Password")
        .unwrap();

    let db = conn.db("Test").unwrap();

    let aql = AqlQuery::builder()
        .query("INSERT @user INTO @@collection LET result = NEW RETURN result")
        .bind_var("@collection", COLLECTION)
        .bind_var("user", user)
        .build();

    let result: Vec<Value> = db.aql_query(aql).expect("Query failed");
}

I cannot compile, as:
^^^^^^^^ the trait 'std::convert::From<User>' is not implemented for 'serde_json::value::Value'

@arn-the-long-beard
Copy link
Contributor

Hello!!

Thank you for your post !

Yeah it seems we have something weird there.

Let ' me write an example with a PR and I come back to you, sounds good for you ?

@inzanez
Copy link
Contributor Author

inzanez commented Aug 11, 2020

Well, yes, and thanks for the answer! But I think I figured it out:

const COLLECTION: &str = "users";

#[derive(Serialize)]
pub struct User {
    name: String,
}

fn main() {
    let user = User { name: "Tester".to_string() };
    let conn = Connection::establish_jwt("http://localhost:8529", "root", "Password")
        .unwrap();

    let db = conn.db("Test").unwrap();

    let json = serde_json::to_value(&user).unwrap();
    let aql = AqlQuery::builder()
        .query("INSERT @user INTO @@collection LET result = NEW RETURN result")
        .bind_var("@collection", COLLECTION)
        .bind_var("user", json)
        .build();

    let result: Vec<Value> = db.aql_query(aql).expect("Query failed");
}

So convert the struct to a serde_json::value::Value, not a string! Now it works.

let json = serde_json::to_value(&user).unwrap();

@arn-the-long-beard
Copy link
Contributor

Hoo mate thank you 👍

I had the same issue as you actually. Thank you for your response. I PR an example so people know where to look in the future !

@arn-the-long-beard
Copy link
Contributor

Do you still have this issue by the way ?

However, that fails, as the query generated escapes the double quotes in the JSON that I generated. Resulting in this:
{"query":"INSERT @client INTO @@collection LET result = NEW RETURN result","bindVars":{"client":"{"name":"Tester"}","@collection":"fs_clients" }

@fMeow
Copy link
Owner

fMeow commented Aug 11, 2020

You could assign the user struct directly by using try_bind instead of bind_var.

try_bind accepts any serializable struct while bind_var only allow struct that can be converted into serde_json::Value. Also, try_bind is failable that it returns a Result<_,_>.

Oh I found the doc doesn't contain discription on how to use AqlQueryBuilder, that is something to be improved.

@inzanez
Copy link
Contributor Author

inzanez commented Aug 14, 2020

Yes, I agree, try_bind works exactly as I expected. Many thanks!

@inzanez inzanez closed this as completed Aug 14, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants