Update data from one Map to another - rust

How can I do the following.
Suppose I have the following document created
{
"_id": "12345",
"email": "julio#gmail.com",
"password": "julio123",
"created": "2021-08-17",
"status": "0"
}
and now through the created document I wish to have a new document like the following one.
{
"email": "julio#gmail.com",
"password": "julio123",
"status": "1"
}
I don't know if what I did is correct, but I know that more code is missing.
#[cfg(test)]
mod tests {
use serde_json::{Map, json};
#[test]
fn prueba() {
let mut user = Map::new();
user.insert("id".to_string(), json!("12345"));
user.insert("email".to_string(), json!("juan#gmail.com"));
user.insert("password".to_string(), json!("juan123"));
user.insert("created".to_string(), json!("2021-08-17"));
user.insert("status".to_string(), json!("0"));
println!("user: {:#?}", user);
let user2 = user.into_iter().fold(Map::new(), |mut user_map, (key, val)| {
user_map.insert(key.clone(), val.clone());
user_map
});
println!("user2: {:#?}", user2);
}
}
I'm just learning to use functional programming, I need help to get the best possible result.

What you seem to want to achieve is to filter and update some fields, creating a new object as a result.
Here is how you might do that:
let user2 = user
.into_iter()
.filter_map(|(k, v)| match k.as_str() {
"email" => Some((k, v)),
"password" => Some((k, v)),
"status" => Some((k, json!("1"))),
_ => None,
})
.collect::<Map<_, _>>();

Related

Idiomatic Rust for Vec<Vec<String>> filter

Very new to programming and for some reason i chose rust to start with but i digress...
Current code to take a reference to a vec of vec strings, compare one 'Column' against some array and return the row and a truncated version of the row.
The below compiles, but i keep re-using this same logic across all my functions and would be really useful to just have some kind of closure.
fn niacs(vec:&Vec<Vec<String>>, naics: Vec<&str> ) -> (Vec<Vec<String>>,Vec<Vec<String>>) {
let mut return_vec_truncated = vec![];
let mut return_vec_full = vec![];
let mut contains_naice = false;
for i in vec.iter() {
for naic in naics.iter(){
if i[31] == *naic {
contains_naice = true;
}
if contains_naice {
let x = info_wanted(&i);
return_vec_truncated.push(x);
return_vec_full.push(i.clone());
}
contains_naice = false;
}
}
(return_vec_full, return_vec_truncated)
}
What i would like to be able to do is write something like:
let x = vec.iter().map(|x| x.iter()).filter(|x| x != naics);
The problem is.. I don't want to map across all of the elements per say, i just want to make across one column within the inner vec, which is column 31.
Sample Vec of Vec:
["471", "001020887", "", "1SNH0", "", "A", "Z2", "20020312", "20210711", "20200731", "20200731", "BENCHMARK INTERNATIONAL, INC", "", "", "", "5025 PIRATES COVE RD", "", "JACKSONVILLE", "FL", "32210", "8309", "USA", "04", "19990208", "1231", "http://www.bmiint.com", "2L", "VA", "USA", "0005", "27~2X~A5~QF~XS", "541611", "", "0002", "541611Y~541690Y", "0000", "", "N", "", "5025 PIRATES COVE RD", "", "JACKSONVILLE", "32210", "8309", "USA", "FL", "ANNA", "", "MCKENZIE", "", "5025 PIRATES COVE RD", "", "JACKSONVILLE", "32210", "8309", "USA", "FL", "4437170460", "", "", "", "amckenzie#bmiint.com"], ["472", "001021310", "", "94867", "", "A", "Z2", "19980424", "20210323", "20200323", "20200323", "CHURCHILL CORPORATION", "", "", "", "344 FRANKLIN ST", "", "MELROSE", "MA", "02176", "1825", "USA", "05", "19480101", "0731", "", "2L", "MA", "USA", "0002", "2X~MF", "332322", "", "0001", "332322Y", "0000", "", "Y", "", "P.O.BOX 761038", "", "MELROSE", "02176", "1825", "USA", "MA", "MARSHALL", "W", "SCHERMERHORN", "", "P.O. BOX 761038", "344 FRANKLIN STREET", "MELROSE", "02176", "", "USA", "MA", "7816654700", "", "", "7816625291", "marshall#atrbox.com"]]
First, to confirm that I'm not overlooking something:
Your code is equal to
fn niacs(vec: &Vec<Vec<String>>, naics: Vec<&str>) -> (Vec<Vec<String>>, Vec<Vec<String>>) {
let mut return_vec_truncated = vec![];
let mut return_vec_full = vec![];
for i in vec.iter() {
for naic in naics.iter() {
if i[31] == *naic {
return_vec_truncated.push(info_wanted(&i));
return_vec_full.push(i.clone());
}
}
}
(return_vec_full, return_vec_truncated)
}
and the contains_naice is unnecessary? Except for contains_naice, I think your code easy to read and plenty idiomatic.
If you absolutely want to write it with iterators, you can use flat_map and unzip:
fn niacs(vec: &Vec<Vec<String>>, naics: Vec<&str>) -> (Vec<Vec<String>>, Vec<Vec<String>>) {
vec.iter()
.flat_map(|i| naics.iter().filter(|naic| i[31] == **naic).map(move |_| i))
.map(|i| (i.clone(), info_wanted(&i)))
.unzip()
}
Though I do wonder: Is that actually what you wanted? Do you really want one copy of i per matching naic? Or do you maybe want one copy of i if any of the naics match?
fn niacs(vec: &Vec<Vec<String>>, naics: Vec<&str>) -> (Vec<Vec<String>>, Vec<Vec<String>>) {
vec.iter()
.filter(|i| naics.iter().any(|naic| i[31] == *naic))
.map(|i| (i.clone(), info_wanted(&i)))
.unzip()
}
(The equal iterative code would have a break inside the if.)

Use a wildcard for extract just one type of data

I have a translations structure like the following:
{
"hello": {
"es": "Hola",
"en": "Hello"
},
"hello2": {
"es": "Hola2"
}
}
I want to extract for example the "es" language only. I know I can get all and extract the data with javascript but i want to be if its possible with mongo.
I tried:
let exists = await col.find({}).project({ $regex: { '*.en': 1 } }).toArray()
But dosen't works.

maxminddb-rust, get value of country for certain language

I decided to start learning Rust, I haven't finished their book yet but I am trying to build and run other projects so I can learn from the source code. I am now interested in maxmind-rust crate and specifically I want to retrieve country, city and asn values from the .mmdb file.
I tried to convert struct maxmind::geoip2::Country to string and use json crate but resulted in errors that I couldn't fix myself.
The code used:
use maxminddb::geoip2;
use std::net::IpAddr;
use std::str::FromStr;
fn main()
{
let mmdb_file = maxminddb::Reader::open("C:\\path\\to\\GeoLite2-City.mmdb").unwrap();
let ip_addr: IpAddr = FromStr::from_str("8.8.8.8").unwrap();
let geoip2_country: geoip2::Country = mmdb_file.lookup(ip_addr).unwrap();
println!("{:?}", geoip2_country);
}
The output is:
Country
{
continent: Some(Continent
{
code: Some("NA"),
geoname_id: Some(6255149),
names: Some(
{
"de": "Nordamerika",
"en": "North America",
"es": "Norteam?rica",
"fr": "Am?rique du Nord",
"ja": "?????",
"pt-BR": "Am?rica do Norte",
"ru": "???????? ???????",
"zh-CN": "???"
})
}),
country: Some(Country
{
geoname_id: Some(6252001),
iso_code: Some("US"),
names: Some(
{
"de": "USA",
"en": "United States",
"es": "Estados Unidos",
"fr": "?tats-Unis",
"ja": "???????",
"pt-BR": "Estados Unidos",
"ru": "???",
"zh-CN": "??"
})
}),
registered_country: Some(Country
{
geoname_id: Some(6252001),
iso_code: Some("US"),
names: Some(
{
"de": "USA",
"en": "United States",
"es": "Estados Unidos",
"fr": "?tats-Unis",
"ja": "???????",
"pt-BR": "Estados Unidos",
"ru": "???",
"zh-CN": "??"
})
}),
represented_country: None,
traits: None
}
which is the maxminddb::geoip2::Country struct (http://oschwald.github.io/maxminddb-rust/maxminddb/geoip2/struct.Country.html)
Changing the last line of code to
println!("{:?}", geoip2_country.country);
outputs only the country field:
country: Some(Country
{
geoname_id: Some(6252001),
iso_code: Some("US"),
names: Some(
{
"de": "USA",
"en": "United States",
"es": "Estados Unidos",
"fr": "?tats-Unis",
"ja": "???????",
"pt-BR": "Estados Unidos",
"ru": "???",
"zh-CN": "??"
})
}),
But looking at the structure of maxminddb::geoip2::model::Country (http://oschwald.github.io/maxminddb-rust/maxminddb/geoip2/model/struct.Country.html), I am very confused as to how I can retrieve from this struct and its pair (language_code, country_name) if I wanted to get the name of country for "en" key.
You could have a look at how the tests are written and it will give you some idea how to extract the information you are looking for:
https://github.com/oschwald/maxminddb-rust/blob/master/src/maxminddb/reader_test.rs
(actually, after looking at the tests I didn't find any example extracting what you are looking for)
That should return what you expect:
let country_name = geoip2_country.country
.and_then(|cy| cy.names)
.and_then(|n| n.get("en")
.map(String::from));

id cannot be used in graphQL where clause?

{
members {
id
lastName
}
}
When I tried to get the data from members table, I can get the following responses.
{ "data": {
"members": [
{
"id": "TWVtYmVyOjE=",
"lastName": "temp"
},
{
"id": "TWVtYmVyOjI=",
"lastName": "temp2"
}
] } }
However, when I tried to update the row with 'id' where clause, the console shows error.
mutation {
updateMembers(
input: {
values: {
email: "testing#test.com"
},
where: {
id: 3
}
}
) {
affectedCount
clientMutationId
}
}
"message": "Unknown column 'NaN' in 'where clause'",
Some results from above confused me.
Why the id returned is not a numeric value? From the db, it is a number.
When I updated the record, can I use numeric id value in where clause?
I am using nodejs, apollo-client and graphql-sequelize-crud
TL;DR: check out my possibly not relay compatible PR here https://github.com/Glavin001/graphql-sequelize-crud/pull/30
Basically, the internal source code is calling the fromGlobalId API from relay-graphql, but passed a primitive value in it (e.g. your 3), causing it to return undefined. Hence I just removed the call from the source code and made a pull request.
P.S. This buggy thing which used my 2 hours to solve failed in build, I think this solution may not be consistent enough.
Please try this
mutation {
updateMembers(
input: {
values: {
email: "testing#test.com"
},
where: {
id: "3"
}
}
) {
affectedCount
clientMutationId
}
}

invalid argument type in call to function 'ATTRIBUTES()' in ArangoDB

I have stored my Data in the give formate in AreangoDB, My collection name in DSP:
"data": {
"1": [ {"db_name": "DSP"}, {"rel": "2"} ],
"2": [ {"rel_name": "DataSource"}, {"tuple": "201"}, {"tuple": "202"}, {"tuple": "203"} ],
"201": [ {"src_id": "Pos201510070"}, {"src_name": "Postgres"}, {"password": "root"}, {"host": "localhost"}, {"created_date": "20151007"}, {"user_name": "postgres"}, {"src_type": "Structured"}, {"db_name": "postgres"}, {"port": "None"} ],
"202": [ {"src_id": "pos201510060"}, {"src_name": "Postgres"},{"password": "root"}, {"host": "localhost"}, {"created_date": "20151006"}, {"user_name": "postgres"}, {"src_type": "Structured"}, {"db_name": "DSP"}, {"port": "5432"} ],
"203": [ {"src_id": "pos201510060"}, {"src_name": "Postgres"}, {"password": "root"}, {"host": "localhost"}, {"created_date": "20151006"}, {"user_name": "postgres"},{"src_type": "Structured"},{"db_name": "maindb"},{"port": "5432"} ]
}
I am executing a query with the above data in the following format:
FOR p IN NestedDSP
LET attributes = ATTRIBUTES(p)
FOR attribute IN attributes
LET key = ATTRIBUTES(attribute)[0]
LET value = attribute[key]
RETURN { subject: attribute, predicate: key, object: value }
When I submit my query to ArangoDB, it returns the response as:
Warnings:
[1542], 'invalid argument type in call to function 'ATTRIBUTES()''
[1542], 'invalid argument type in call to function 'ATTRIBUTES()''
[1542], 'invalid argument type in call to function 'ATTRIBUTES()''
[1542], 'invalid argument type in call to function 'ATTRIBUTES()''
Result:
[
{
"subject": "data",
"predicate": null,
"object": null
},
{
"subject": "_id",
"predicate": null,
"object": null
},
{
"subject": "_rev",
"predicate": null,
"object": null
},
{
"subject": "_key",
"predicate": null,
"object": null
}
]
Please tell me what is the problem with this query, and why the answer is like the above..I am working in ArangoDB-2.7.3-win64.
Thanks
Let me demonstrate how to construct such a complex query digging deep into nested data structures. I start out taking the outer parts of the query, to have an inner result:
FOR p IN NestedDSP
LET attributes = ATTRIBUTES(p)
FOR attribute IN attributes
RETURN attribute
which gives me:
[
"data",
"_rev",
"_key",
"_id"
]
So lets dive deeper into the next layer. I guess you're only interested in the values present underneath data key right? so we pick p.data:
FOR p IN NestedDSP
LET attributes = ATTRIBUTES(p.data)
FOR attribute IN attributes
RETURN attribute
which then gives me the keys for your next inner array:
[
"203",
"202",
"201",
"2",
"1"
]
We now explore what we find attached to these nodes:
FOR p IN NestedDSP
LET attributes = ATTRIBUTES(p.data)
FOR oneAttribute IN attributes
LET keys = p.data[oneAttribute]
RETURN keys
Its Again an array, which we need to iterate into using a FOR loop over keys:
[
[
{
"src_id" : "pos201510060"
},
{
"src_name" : "Postgres"
}, ...
We add this additional FOR-loop:
FOR p IN NestedDSP
LET attributes = ATTRIBUTES(p.data)
FOR oneAttribute IN attributes
LET keys = p.data[oneAttribute]
FOR key IN keys
RETURN key
we get the inner most objects:
[
{
"src_id" : "pos201510060"
},
{
"src_name" : "Postgres"
},
{
"password" : "root"
},
...
You wanted to use the ATTRIBUTES function, but the objects only have one member, so we can access [0]:
FOR p IN NestedDSP
LET attributes = ATTRIBUTES(p.data)
FOR oneAttribute IN attributes
LET keys = p.data[oneAttribute]
FOR key IN keys
LET keyAttributes=ATTRIBUTES(key)
RETURN keyAttributes
Which gives us the object keys, one per inner most object:
[
[
"src_id"
],
[
"src_name"
],
We inspect whether we now get only the object keys of the inner most structure; we pick the variable names a little more clever than above:
FOR p IN NestedDSP
LET attributes = ATTRIBUTES(p.data)
FOR oneAttribute IN attributes
LET pairs = p.data[oneAttribute]
FOR onePair IN pairs
LET pairKey=ATTRIBUTES(onePair)[0]
RETURN pairKey
YES:
[
"src_id",
"src_name",
"password",
"host",
...
So now its time to construct the results object as you wanted them:
FOR p IN NestedDSP
LET attributes = ATTRIBUTES(p.data)
FOR oneAttribute IN attributes
LET pairs = p.data[oneAttribute]
FOR onePair IN pairs
LET pairKey=ATTRIBUTES(onePair)[0]
RETURN { subject: oneAttribute, predicate: pairKey, object: onePair[pairKey] }
The subject is the number identifying the outermost item, the predicate is the object key, and the object is the value in it:
[
{
"subject" : "203",
"predicate" : "src_id",
"object" : "pos201510060"
},
{
"subject" : "203",
"predicate" : "src_name",
"object" : "Postgres"
}
Which is hopefully what you wanted?

Resources