My gradepoints and percents objects hold the same values of grades with different keys. Please take a look at my json below and let me know if I'm doing it right. Is there a way to optimize this API?
I could provide the percents along with the gradepoints after a comma like "a1": "10,90" but this way I will need to split them up on client side JS, which I'm restraining from.
{
"gradepoints": [
{
"a1": 10
},
{
"a1": 10
},
{
"c2": 5
},
{
"e1": "eiop"
},
{
"d": 4
},
{
"b1": 8
}
],
"percents": [
{
"a1": 90
},
{
"a1": 90
},
{
"c2": 45
},
{
"e1": "eiop"
},
{
"d": 36
},
{
"b1": 72
}
],
"gpa": 7.4,
"overall": 70.3,
"eiop": 2
}
I would do it something like this:
{
grades: [
{ name: "a1",
gradepoint: 10,
percent: 90
},
{ name: "a1",
gradepoint: 10,
percent: 90
},
{ name: "c2",
gradepoint: 5,
percent: 45
},
...
],
gpa: 7.4,
overall: 70.3,
eiop: 2
}
Related data should be kept together in an object.
If it weren't for the duplicate a1 entries, I would probably make grades be an object, with the names as keys. But an object can't have duplicate keys, so it has to be put in the values.
Related
I know that common table expressions (CTE) a.k.a. "temporary named result sets" can be used in SQL to generate a temporary table, but can this be done in MongoDB? I want a document, but it's only for temporary use in my query.
Can you create a temporary table in MongoDB without creating a new collection?
For example, if I were to try to recreate the code below in Mongo...
Example CTE Table in SQL:
n
f1
f2
1
20
12
2
40
0.632
3
60
0.647
WITH RECURSIVE example (n, f1, f2) AS
( SELECT 1, 20, 12
UNION ALL SELECT
n + 1,
n * 20,
least(6*n, $globalVar * 100),
FROM example WHERE n < 3
) SELECT * FROM example
It seems that there is no general equivalent for CTE in MongoDB. However, for OP's example, it is possible to wrangle the output of $range to produce a similar effect.
// whichever collection doesn't matter; as long as it has 1 document then it should be fine
db.collection.aggregate([
{
// jsut take 1 document
"$limit": 1
},
{
// use $range to generate iterator [1, 2, 3]
"$addFields": {
"rg": {
"$range": [
1,
4
]
},
globalVar: 0.001
}
},
{
// do the mapping according to logic
"$addFields": {
"cte": {
"$map": {
"input": "$rg",
"as": "n",
"in": {
n: "$$n",
f1: {
"$multiply": [
"$$n",
20
]
},
f2: {
"$cond": {
"if": {
$lt: [
{
"$multiply": [
"$$n",
6
]
},
{
"$multiply": [
"$globalVar",
100
]
}
]
},
"then": {
"$multiply": [
"$$n",
6
]
},
"else": {
"$multiply": [
"$globalVar",
100
]
}
}
}
}
}
}
}
},
{
// wrangle back to expected form
"$unwind": "$cte"
},
{
"$replaceRoot": {
"newRoot": "$cte"
}
}
])
Here is the Mongo playground for your reference.
i'm trying to convert the inspection_date field from string to date for every object inside my db.
Every object is built like this one.
"name": "$1 STORE",
"address": "5573 ROSEMEAD BLVD",
"city": "TEMPLE CITY",
"zipcode": "91780",
"state": "California",
"violations": [{
"inspection_date": "2015-09-29",
"description": " points ... violation_status\n62754 1 ... OUT OF COMPLIANCE\n62755 1 ... OUT OF COMPLIANCE\n62756 2 ... OUT OF COMPLIANCE\n\n[3 rows x 5 columns]",
"risk": "Risk 3 (Low)"
}, {
"inspection_date": "2016-08-18",
"description": " points ... violation_status\n338879 2 ... OUT OF COMPLIANCE\n\n[1 rows x 5 columns]",
"risk": "Risk 3 (Low)"
} //could be more than 2 or less then 2 object inside violations array//]}
How can i convert all of the inspection_date field avoiding doing it by myself one by one?
As suggested by #turivishal, you have to have to make use of $map and $dateFromString operators.
db.collection.aggregate([
{
"$addFields": {
"violations": {
"$map": {
"input": "$violations",
"in": {
"$mergeObjects": [
"$$this",
{
"inspection_date": {
"$dateFromString": {
"dateString": "$$this.inspection_date",
"format": "%Y-%m-%d",
"onError": null,
"onNull": null
}
}
}
],
},
}
}
}
},
])
Mongo Playground Sample Execution
I have imported the above json data into it's own collection on mongoDB database. I'm trying to aggregate the values (ie 40, 30, 30) and SUM and AVG them as they reside in the inner most embedded document. I'm having a problem doing this when I try using dot notation and can not get any vaules. I feel the unique timestamps (ie 1567544426000, 1567541464000, 1567541475000) are a problem. Is this json file formatted correctly for aggregation and how would I do so. Thanks for any help or if you can even point me in the right direction where I can find out how to do SUM, AVG etc to the data.
I've tried use NoSQLBooster and Query ASsist for MongoDB
{
"Barcode": "97-1908-577-1032-BE1-332",
"IP": "192.162.656.111",
"VFD": {
"CurrentPV": {
"Type": "Speed",
"Data": {
"1567544426000": 40,
"1567541464000": 30
"1567541475000": 30
}
},
"CurrentSP": {
"Type": "Speed",
"Data": {
"1567544426000": 55,
"1567541464000": 5
"1567541488000": 10
}
},
"Program_Running": {
"Type": "Active",
"Data": {
"1567544426000": 1,
"1567541464000": 0
"1567541475000": 3
}
}
},
"Equipment": "PieceOfEquipment",
"Location": "Garage",
"RunEnd": "NA",
"RunStart": 1533541438
}
I can't seem to reach the values even when I use dot notation down to the "Data" branch object (ie Equipment.VFD.CurrentPV.Data) but no result sets are returned.
We can convert the VFD.CurrentPV.Data into an array of key-value pairs using $objectToArray and then perform SUM and AVG on the values itself.
The following query can get us the expected output:
db.collection.aggregate([
{
$addFields:{
"data":{
$objectToArray: "$VFD.CurrentPV.Data"
}
}
},
{
$project:{
"sum":{
$sum:"$data.v"
},
"avg":{
$avg:"$data.v"
}
}
}
]).pretty()
Data set:
{
"_id" : ObjectId("5d830f3afb35a835fbd8638e"),
"Barcode" : "97-1908-577-1032-BE1-332",
"IP" : "192.162.656.111",
"VFD" : {
"CurrentPV" : {
"Type" : "Speed",
"Data" : {
"1567544426000" : 40,
"1567541464000" : 30,
"1567541475000" : 30
}
},
"CurrentSP" : {
"Type" : "Speed",
"Data" : {
"1567544426000" : 55,
"1567541464000" : 5,
"1567541488000" : 10
}
},
"Program_Running" : {
"Type" : "Active",
"Data" : {
"1567544426000" : 1,
"1567541464000" : 0,
"1567541475000" : 3
}
}
},
"Equipment" : "PieceOfEquipment",
"Location" : "Garage",
"RunEnd" : "NA",
"RunStart" : 1533541438
}
Output:
{
"_id" : ObjectId("5d830f3afb35a835fbd8638e"),
"sum" : 100,
"avg" : 33.333333333333336
}
I'm trying to increment c every time a user choose a label.
My sample dataset has two nested arrays:
{
"id": 123,
"labels": [
{
"label": "orange",
"hitCount": 2,
"hits": [
{
"who": "bob",
"c": "2"
}
]
},
{
"label": "red",
"hitCount": 6,
"hits": [
{
"who": "bob",
"c": "5"
},
{
"who": "alice",
"c": "1"
}
]
}
]
}
For example bob choose again red so I want to increment the c inside bob's object inside red's object from 5 to 6.
I can't use $ two times to navigate inside more than one array per https://docs.mongodb.com/manual/reference/operator/update/positional/#nested-arrays
So anyone knows how to traverse more than one level of array and obtain a reference for $inc?
I suggest you to change you data model to:
{
"id": 123,
"labels": [
{
"label": "orange",
"hitCount": 2,
"hits": {
"bob": 2
}
},
{
"label": "red",
"hitCount": 6,
"hits": {
"bob":5,
"alice":1
}
}
]
}
Then you could update hits using this command:
db.hits.update(
{ 'labels.label': 'red' },
{ '$inc': { 'labels.$.hitCount': 1, 'labels.$.hits.bob': 1 } }
);
If you need to construct update with dynamic username, you can do it:
var userName = 'bob';
var updateCommand = {
$inc: {
'labels.$.hitCount': 1
}
};
updateCommand.$inc['labels.$.hits.' + userName] = 1;
db.hits.update({ 'labels.label': 'red' }, updateCommand);
I came to read the json file to output to an highcharts.
I have a highcharts areagraph whose values are received from json whose format is as follows:
scope.jsondata = [
{
"Name": "A",
"Categories": "03.01",
"Locate": "1",
"Value": 30
},
{
"Name": "A",
"Categories": "03.02",
"Locate": "1",
"Value": 50
},
{
"Name": "A",
"Categories": "03.03",
"Locate": "1",
"Value": 60
},
{
"Name": "A",
"Categories": "03.04",
"Locate": "1",
"Value": 40
},
{
"Name": "A",
"Categories": "03.05",
"Locate": "1",
"Value": 70
}
];
How can I embed those values for my jsondata in angularJS?
scope.render = function (data) {
var target = element.find('#detail-usage-chart'),
firstDate = {
name: scope.jsondata.Name,
data: scope.jsondata.Vaule,
color: '#f48d7f',
type: 'area'
},
tempOption = {
data: [10, 13, 17, 8, 11, 5, 11, 13 ,16, 18, 20, 13, 16, 21, 19],
type: 'spline',
yAxis: 1
}
};
Please provide a suitable way to embed the data from json.
Area chart is expecting a name and an array contaning values in its series:
See here
So all you have to do is just a quick function in order to prepare your data that way. For example:
var scope.readyValues = [];
for(var i=0;i<scope.jsondata.length;i++)
{
scope.readyValues.push(scope.jsondata[i].Value);
}
Next, just configure the series this way:
// .....chart options
series: [{
name: scope.jsondata[0].Name,
data: scope.readyValues
}
If you have multiple Names in your scope.jsondata then you can use jquery map function or you can make an array for each name.
And since you're using angular I recommend you use Highcharts-ng it's easier ;)