Looking To Update/Increase Embedded Array Objects Numeric Value - json

I have the following item within my Mongo DB Collection
db.teams.insert({
team_id: "spa2",
date_founded: new Date("Nov 04, 1914"),
league: "La Liga",
points: 72,
name: "Real Madrid",
players: [ { p_id: "Ronaldo", goal: 135, caps: 134, age: 28 },
{ p_id: "Bale", goal: 75, caps: 45, age: 27 },
{ p_id: "Marcelo", goal: 11, caps: 25, age: 31 },
{ p_id: "Benzema", goal: 125, caps: 95, age: 22 } ]
});
I want to be able to increase the number of goals scored by 3.
I have tried all morning to find a demo of this, but cant find anything near enough for me to get it to work.

To increase the number you should use $inc operator. To do that for one particular document inside players array you should use positional operator.
So entire operations should look like this:
db.teams.update({_id: ObjectId("5a48d65f3a1e3fc4b06b787f"), "players.p_id": "Ronaldo"}, {$inc: {"players.$.goal": 3}})
This will update only goals for Ronaldo. If you want to update goals for all players you should use the new all positional operator $[]
db.teams.update({_id: ObjectId("5a48d65f3a1e3fc4b06b787f")}, {$inc: {"players.$[].goal": 3}})

Related

Return a value of dictionary where a variable is inbetween keys or values

I have some data that I think would work best as a dictionary or JSON. The data has an initial category, a, b...z, and five bands within each category.
What I want to be able to do is give a function a category and a value and for the function to return the corresponding band.
I tried to create a dictionary like this where the values of each band are the lower threshold i.e. for category a, Band 1 is between 0 and 89:
bandings = {
'a' :
{
'Band 1' : 0,
'Band 2': 90,
'Band 3': 190,
'Band 4': 420,
'Band 5': 500
},
'b' :
{
'Band 1' : 0,
'Band 2': 500,
'Band 3': 1200,
'Band 4': 1700,
'Band 5': 2000
}
}
So if I was to run a function:
lookup_band(category='a', value=100)
it would return 'Band 3' as 100 is between 90 and 189 in category a
I also experimented with settings keys as ranges but struggled with how to handle a range of > max value in Band 5.
I can change the structure of the dictionary or use a different way of referencing the data.
Any ideas, please?
You can structure your data a little bit differently (using sorted lists instead of dictionaries) and use bisect module. For example:
from bisect import bisect
bandings = {
'a': [0, 90, 190, 420, 500],
'b': [0, 500, 1200, 1700, 2000]
}
def lookup_band(bandings, band, value):
return 'Band {}'.format(bisect(bandings[band], value))
print(lookup_band(bandings, 'a', 100)) # Band 2
print(lookup_band(bandings, 'b', 1700)) # Band 4
print(lookup_band(bandings, 'b', 9999)) # Band 5

How do I convert MySQL BINARY columns I created with Node Buffers to strings in Rust?

What I did
Stored a UUID as BINARY(16) in NodeJS using
const uuid = Buffer.from('myEditedUuid');
(A followup to How do I fetch binary columns from MySQL in Rust?)
What I want to do
I want to fetch said UUID using Rust https://docs.rs/mysql/20.0.0/mysql/.
I am currently using Vec<u8> to gain said UUID:
#[derive(Debug, PartialEq, Eq, Serialize)]
pub struct Policy {
sub: String,
contents: Option<String>,
}
#[derive(Debug, PartialEq, Eq, Serialize)]
pub struct RawPolicy {
sub: Option<Vec<u8>>,
contents: Option<String>,
}
// fetch policies themselves
let policies: Vec<RawPolicy> = connection.query_map("SELECT sub, contents FROM policy", |(sub, contents)| {
RawPolicy { sub, contents }
},)?;
// convert uuid to string
let processed = policies.into_iter().map(|policy| {
let sub = policy.sub.unwrap();
let sub_string = String::from_utf8(sub).unwrap().to_string();
Policy {
sub: sub_string,
contents: policy.contents,
}
}).collect();
What my problem is
In Node, I would receive a Buffer from said database and use something like uuidBUffer.toString('utf8');
So in Rust, I try to use String::from_utf8(), but said Vec does not seem to be a valid utf8-vec:
panicked at 'called `Result::unwrap()` on an `Err` value: FromUtf8Error { bytes: [17, 234, 79, 61, 99, 181, 10, 240, 164, 224, 103, 175, 134, 6, 72, 71], error: Utf8Error { valid_up_to: 1, error_len: Some(1) } }'
My question is
Is Using Vec correct way of fetching BINARY-Columns and if so, how do I convert them back to a string?
Edit1:
Node seems to use Base 16 to Convert A string to a Buffer (Buffer.from('abcd') => <Buffer 61 62 63 64>).
Fetching my parsed UUID in Rust made With Buffer.from() gives me Vec<u8> [17, 234, 79, 61, 99, 181, 10, 240, 164, 224, 103, 175, 134, 6, 72, 71] which thows said utf8-Error.
Vec does not seem to be allowed by MySQL in Rust.
Solution is simple:
You need to convert the BINARY to hex at you database Query or you code. So either try Using the HEX-Crate https://docs.rs/hex/0.4.2/hex/ or rewrite your Query:
Rewriting The Query
let policies: Vec<RawPolicy> = connection.query_map("SELECT hex(sub), contents FROM policy", |(sub, contents)| {
RawPolicy { sub, contents }
},)?;
Converts the sub to hex numbers. Now the resulting Vec can be converted using
let sub = policy.sub.unwrap();
let sub_string = String::from_utf8(sub).unwrap();
from_utf8_lossy can be used
let input = [17, 234, 79, 61, 99, 181, 10, 240, 164, 224, 103, 175, 134, 6, 72, 71];
let output = String::from_utf8_lossy(&input); // "\u{11}�O=c�\n��g��\u{6}HG"
Invalid characters will be replaced by �
The output "\u{11}�O=c�\n��g��\u{6}HG" is the same as the nodejs output "\u0011�O=c�\n��g��\u0006HG".
Unless this string is to be send to a javascript runtime, it should be kept that way.
But if this string is to be send to a javascript runtime (browser or nodejs), then the unicode point notations\u{x} should be substituted to their equivalent notation in javascript
playground
from_ut16_lossy can be used as well
If some of the previous � are not utf-8 encoded but utf-16, they will be converted, if not the same � will be used to render them.
let input:&[u16] = &vec![17, 234, 79, 61, 99, 181, 10, 240, 164, 224, 103, 175, 134, 6, 72, 71];
println!("{}", String::from_utf16_lossy(input))
playground

BQ (Big Query) - Modify JSON output, to be accepted by BQ

Currently, using API to collect JSON file. I have managed to extract this output as I demonstrated below.
And now I'm on the stage, that I have JSON extraction and need to make in the way that BQ will accept it. Without too much manipulation ( as this output potentially will be loaded on the daily bases.
{
"stats": [{
"date": "2018-06-17T00:00:00.000Z",
"scores": {
"my-followers": 8113,
"my-listed": 15,
"my-favourites": 5289,
"my-followings": 230,
"my-statuses": 3107
}
}, {
"date": "2018-06-18T00:00:00.000Z",
"scores": {
"my-statuses": 3107,
"my-followings": 230,
"my-lost-followings": 0,
"my-new-followers": 0,
"my-new-statuses": 0,
"my-listed": 15,
"my-lost-followers": 5,
"my-followers": 8108,
"my-favourites": 5288,
"my-new-followings": 0
}
}
.....
],
"uid": "123456789"
}
ANy help will be appreciated.
Currently I have this error:
Errors:
query: Invalid field name "my-new-followings". Fields must contain only letters, numbers, and underscores, start with a letter or underscore, and be at most 128 characters long. Table: link_t_perf_test1_b58d4465_3a31_40cb_987f_9fb2d1de29dc_source (error code: invalidQuery
Even when "my-new-followings" contain only integer (up to 5 digit) number.

How to show multiple lines in google-chart linr-graph

I have polymer code like this:
<google-chart type='line' options='{"title": "Sales Statistics, Billions", "vAxis": {"minValue" : 0, "maxValue": 40}, "curveType": "function"}' rows='[["Monday", 31], ["Tuesday", 28], ["Wednesday", 31], ["thursday", 22], ["friday", 11]]' cols='[{"label":"Weeks", "type":"string"}, {"label":"Days", "type":"number"}]'></google-chart>
The code works fine. But, I don't know how to show multiple lines of data.
That means my output is
I want like this:
Thanks.
I found solution for my problem. Add another element to cols array as
cols='[{"label":"Weeks", "type":"string"}, {"label":"Days", "type":"number"}, {"label":"Days", "type":"number"}]'
And add another element to array of the rows, which acts as co-ordinates for another line in the graph as
rows='[["Monday", 31, 11], ["Tuesday", 28, 22], ["Wednesday", 31, 33], ["thursday", 22, 44], ["friday", 11, 44]]'
Thanks.

pandas: how to create dataframe from dict of lists

How do I convert this into a pandas dataframe?
df_components = { "result1":
{"data" : [["43", "48", "27", "12"], ["67", "44", "24", "11"], ["11.85", "6.31", "5.18", "11.70"]],
"index" : [["Device_use_totala11. PS4", "Unweighted base"], ["Device_use_totala11. PS4", "Base"], ["Device_use_totala11. PS4", "Mean"]],
"columns" : [["Age", "Under 30"], ["Age", "30-44"], ["Age", "45-54"], ["Age", "55+"]]}
}
It's a dict with list of lists.
I thought this would work but it returns something funky which doesnt look like a dataframe
pd.DataFrame(df_components['result1'])
Output looks like:
columns [[Age, Under 30], [Age, 30-44], [Age, 45-54], ...
data [[43, 48, 27, 12], [67, 44, 24, 11], [11.85, 6...
index [[Device_use_totala11. PS4, Unweighted base], ...
Expected output:
a multi index df, something similar to the table below?
Your dict is not formatted properly to transform it directly into a DataFrame, you need to do:
d = df_components["result1"]
df = pd.DataFrame(d["data"],
columns=pd.MultiIndex.from_tuples(d["columns"]),
index=pd.MultiIndex.from_tuples(d["index"]))
df
Age
Under 30 30-44 45-54 55+
Device_use_totala11. PS4 Unweighted base 43 48 27 12
Base 67 44 24 11
Mean 11.85 6.31 5.18 11.70