Storing data from a nested firebase object - javascript

I am working with an attendance web app which displays information month wise.
Here is my structure of firebase database:Firebase Database Structure
To iterate over the data, i use this:
for(i = 0; i<months.length;i++){
console.log(months[i]);
var datesRef = firebase.database().ref('students/' + currentStudentSap + '/attendance/' + currentSem + '/' + months[i]);
datesRef.on('value',function(snapshot){
var dates = snapshot.val();
var date = Object.keys(dates);
for(j=0;j<date.length;j++){
console.log(date[j]);
var lectureRef = firebase.database().ref('students/' + currentStudentSap + '/attendance/' + currentSem + '/' + months[i] + "/" + date[j]);
lectureRef.on('value',function(snapshot){
var lectures = snapshot.val();
console.log(lectures, typeof(lectures));
});
}
});
}
Here is what I get on the console:
Console Data
What I want to do now is save these stats in some data structure so that I can use them to produce graphical charts.
For eg: "COSTtheory" is a subject and I want to calculate total conducted lectures and total present lectures for each month, and display month wise statistics (such as percentage attended) in HTML.

I don't know exactly how you insert data in Firebase but i would not iterate thru it like you do. Instead i would increment the monthly totals i need to make report each time data is inserted, that way i would be able to show live stats (kind of purpose of a live DB). I would use Firebase database transactions with cloud functions to achieve this. Transactions ensure data consistency.

Related

Run javascript in Bubble with loops to compare JSON API data

I'm building an app using Bubble and I have the Toolbox plugin which enables me to use the "Run javascript" step in a Workflow.
From the following NASA API url, I'm planning to read and analyze 20 years of data with values for every month (240 values):
https://power.larc.nasa.gov/api/temporal/monthly/point?parameters=ALLSKY_SFC_SW_DNI&community=RE&longitude=48.0000&latitude=27.0000&format=JSON&start=2001&end=2020
Below is what I am trying to accomplish (with missing pieces of code):
Read in the json data from the API and parse it into an Javascript object.
const response = await fetch(api_url);
const data = await response.json();
Loop through the objects values of interest. Inside the loop calculate the average values for each month. January, February, March, etc.
for(const entry of Object.entries(data.properties.parameters.ALLSKY_SFC_SW_DNI)){}
Store the above 12 average values to the Bubble database.
Loop through the 12 average values to find the two months with highest and lowest value.
Store the above High/low months values to the Bubble database. For example January as lowest average value.
I have successfully learned how to do some basic Javascript operations in Bubble. Reading single values from the API, display them on the page, and store them in the Bubble database. But, I do not know how to read the values in to an JS array, and make the necessary loops and comparisons.
I found this older question but it's about a txt file instead of json in my case.
Get an array of values using fetch api javascript
Appreciate any advice and directions. Thanks
We know the data exists # data.properties.parameter.ALLSKY_SFC_SW_DNI
The year and month are combined so the month must be extracted. Here is one simple way. (note I chose to remove the leading zero for a reason)
/* Given '202001' returns '1', given 202012' returns '12' */
function extractMonth(yearmonth){
let month = yearmonth.substring(yearmonth.length-2);
return month.startsWith('0')? month[month.length-1] : month;
}
If you store the data in a simple Array, the indexes can serve as the Month number. So index 1 will represent January. In order to do that the first element (index 0) will be set to null.
The reasons I took this approach is because the data structure is simple and it makes finding the lowest and highest values quite easy.
Now it is as easy as populating each Array element with the average value inside the loop. Each iteration of the loop updates the average for the month.
for(let [yearmonth, measurement] of Object.entries(data.properties.parameter.ALLSKY_SFC_SW_DNI)){
const month = extractMonth(yearmonth);
if(!tempsByMonth[month]) tempsByMonth[month] = 0;
tempsByMonth[month] = (tempsByMonth[month] + measurement)/2;
}
It looks like this:
const data = {"type":"Feature","geometry":{"type":"Point","coordinates":[48.0,27.0,191.14]},"properties":{"parameter":{"ALLSKY_SFC_SW_DNI":{"200101":5.65,"200102":4.88,"200103":5.28,"200104":5.05,"200105":4.84,"200106":5.21,"200107":5.44,"200108":6.07,"200109":5.72,"200110":5.3,"200111":4.52,"200112":3.03,"200113":5.08,"200201":4.09,"200202":4.89,"200203":4.49,"200204":4.19,"200205":5.17,"200206":6.12,"200207":6.15,"200208":5.64,"200209":5.92,"200210":5.5,"200211":4.57,"200212":3.26,"200213":5.0,"200301":4.55,"200302":3.9,"200303":4.09,"200304":4.29,"200305":4.39,"200306":6.1,"200307":5.29,"200308":6.14,"200309":6.3,"200310":5.28,"200311":3.93,"200312":3.39,"200313":4.81,"200401":3.51,"200402":4.45,"200403":5.37,"200404":4.01,"200405":5.39,"200406":6.4,"200407":6.42,"200408":6.11,"200409":6.21,"200410":5.86,"200411":3.66,"200412":3.89,"200413":5.11,"200501":4.05,"200502":4.03,"200503":4.52,"200504":4.49,"200505":5.14,"200506":5.33,"200507":5.06,"200508":5.85,"200509":6.08,"200510":5.45,"200511":3.89,"200512":4.06,"200513":4.83,"200601":3.65,"200602":3.43,"200603":4.85,"200604":4.0,"200605":4.57,"200606":6.08,"200607":5.01,"200608":5.5,"200609":6.32,"200610":4.81,"200611":4.08,"200612":3.99,"200613":4.7,"200701":4.27,"200702":4.56,"200703":4.39,"200704":3.51,"200705":4.75,"200706":5.4,"200707":5.18,"200708":5.77,"200709":5.88,"200710":5.43,"200711":4.7,"200712":3.76,"200713":4.8,"200801":3.26,"200802":4.12,"200803":4.64,"200804":3.77,"200805":4.03,"200806":4.52,"200807":4.84,"200808":5.3,"200809":4.71,"200810":4.76,"200811":3.97,"200812":5.08,"200813":4.42,"200901":4.08,"200902":3.23,"200903":3.68,"200904":3.66,"200905":4.57,"200906":4.9,"200907":4.23,"200908":4.73,"200909":5.03,"200910":4.57,"200911":4.15,"200912":3.89,"200913":4.23,"201001":4.73,"201002":3.99,"201003":4.51,"201004":3.52,"201005":4.36,"201006":5.12,"201007":4.8,"201008":5.17,"201009":5.28,"201010":5.14,"201011":5.39,"201012":4.65,"201013":4.73,"201101":3.56,"201102":3.47,"201103":4.1,"201104":2.83,"201105":4.52,"201106":4.37,"201107":4.63,"201108":5.31,"201109":5.53,"201110":4.8,"201111":3.71,"201112":4.81,"201113":4.31,"201201":4.19,"201202":3.51,"201203":3.36,"201204":3.34,"201205":3.68,"201206":4.9,"201207":5.33,"201208":5.18,"201209":5.7,"201210":4.84,"201211":4.43,"201212":3.52,"201213":4.33,"201301":3.44,"201302":4.4,"201303":4.03,"201304":3.79,"201305":4.96,"201306":4.94,"201307":4.97,"201308":5.45,"201309":5.39,"201310":5.11,"201311":4.14,"201312":4.38,"201313":4.58,"201401":3.86,"201402":4.49,"201403":4.28,"201404":4.19,"201405":4.78,"201406":5.71,"201407":5.4,"201408":5.37,"201409":5.82,"201410":4.61,"201411":4.21,"201412":4.66,"201413":4.78,"201501":4.24,"201502":3.73,"201503":4.01,"201504":3.79,"201505":4.18,"201506":5.02,"201507":4.7,"201508":5.67,"201509":4.94,"201510":4.17,"201511":3.77,"201512":3.45,"201513":4.31,"201601":4.19,"201602":5.15,"201603":3.77,"201604":4.8,"201605":5.0,"201606":5.73,"201607":4.92,"201608":5.69,"201609":5.49,"201610":5.5,"201611":4.16,"201612":3.46,"201613":4.82,"201701":3.8,"201702":4.54,"201703":3.76,"201704":4.32,"201705":4.89,"201706":7.03,"201707":6.06,"201708":6.37,"201709":6.41,"201710":5.69,"201711":4.48,"201712":4.72,"201713":5.17,"201801":4.6,"201802":4.12,"201803":5.46,"201804":3.69,"201805":5.18,"201806":5.6,"201807":5.71,"201808":5.88,"201809":6.16,"201810":4.48,"201811":3.29,"201812":3.9,"201813":4.85,"201901":2.72,"201902":4.73,"201903":4.92,"201904":4.62,"201905":5.73,"201906":7.4,"201907":5.76,"201908":6.02,"201909":6.66,"201910":5.02,"201911":4.33,"201912":4.65,"201913":5.21,"202001":4.6,"202002":4.85,"202003":5.12,"202004":4.48,"202005":6.14,"202006":6.77,"202007":6.52,"202008":6.37,"202009":6.58,"202010":6.86,"202011":4.21,"202012":3.89,"202013":5.54}}},"header":{"title":"NASA/POWER CERES/MERRA2 Native Resolution Monthly and Annual","api":{"version":"v2.2.12","name":"POWER Monthly and Annual API"},"fill_value":-999.0,"start":"20010101","end":"20201231"},"messages":[],"parameters":{"ALLSKY_SFC_SW_DNI":{"units":"kW-hr/m^2/day","longname":"All Sky Surface Shortwave Downward Direct Normal Irradiance"}},"times":{"data":0.745,"process":0.02}};
const tempsByMonth = [null];
for(let [yearmonth, measurement] of Object.entries(data.properties.parameter.ALLSKY_SFC_SW_DNI)){
const month = extractMonth(yearmonth);
if(!tempsByMonth[month]) tempsByMonth[month] = 0;
tempsByMonth[month] = (tempsByMonth[month] + measurement)/2;
}
function extractMonth(yearmonth){
let month = yearmonth.substring(yearmonth.length-2);
return month.startsWith('0')? month[month.length-1] : month;
}
console.log(tempsByMonth);
Finally, to find the lowest and highest average, you'll use Math.max and Math.min. Note that for the lowest average the null value was filtered out of the list:
console.log('Month with greatest value: ', tempsByMonth.indexOf(Math.max(...tempsByMonth)));
console.log('Month with lowest value: ', tempsByMonth.indexOf(Math.min(...tempsByMonth.filter(v=>v!==null))));
And here is the final result in action:
const data = {"type":"Feature","geometry":{"type":"Point","coordinates":[48.0,27.0,191.14]},"properties":{"parameter":{"ALLSKY_SFC_SW_DNI":{"200101":5.65,"200102":4.88,"200103":5.28,"200104":5.05,"200105":4.84,"200106":5.21,"200107":5.44,"200108":6.07,"200109":5.72,"200110":5.3,"200111":4.52,"200112":3.03,"200113":5.08,"200201":4.09,"200202":4.89,"200203":4.49,"200204":4.19,"200205":5.17,"200206":6.12,"200207":6.15,"200208":5.64,"200209":5.92,"200210":5.5,"200211":4.57,"200212":3.26,"200213":5.0,"200301":4.55,"200302":3.9,"200303":4.09,"200304":4.29,"200305":4.39,"200306":6.1,"200307":5.29,"200308":6.14,"200309":6.3,"200310":5.28,"200311":3.93,"200312":3.39,"200313":4.81,"200401":3.51,"200402":4.45,"200403":5.37,"200404":4.01,"200405":5.39,"200406":6.4,"200407":6.42,"200408":6.11,"200409":6.21,"200410":5.86,"200411":3.66,"200412":3.89,"200413":5.11,"200501":4.05,"200502":4.03,"200503":4.52,"200504":4.49,"200505":5.14,"200506":5.33,"200507":5.06,"200508":5.85,"200509":6.08,"200510":5.45,"200511":3.89,"200512":4.06,"200513":4.83,"200601":3.65,"200602":3.43,"200603":4.85,"200604":4.0,"200605":4.57,"200606":6.08,"200607":5.01,"200608":5.5,"200609":6.32,"200610":4.81,"200611":4.08,"200612":3.99,"200613":4.7,"200701":4.27,"200702":4.56,"200703":4.39,"200704":3.51,"200705":4.75,"200706":5.4,"200707":5.18,"200708":5.77,"200709":5.88,"200710":5.43,"200711":4.7,"200712":3.76,"200713":4.8,"200801":3.26,"200802":4.12,"200803":4.64,"200804":3.77,"200805":4.03,"200806":4.52,"200807":4.84,"200808":5.3,"200809":4.71,"200810":4.76,"200811":3.97,"200812":5.08,"200813":4.42,"200901":4.08,"200902":3.23,"200903":3.68,"200904":3.66,"200905":4.57,"200906":4.9,"200907":4.23,"200908":4.73,"200909":5.03,"200910":4.57,"200911":4.15,"200912":3.89,"200913":4.23,"201001":4.73,"201002":3.99,"201003":4.51,"201004":3.52,"201005":4.36,"201006":5.12,"201007":4.8,"201008":5.17,"201009":5.28,"201010":5.14,"201011":5.39,"201012":4.65,"201013":4.73,"201101":3.56,"201102":3.47,"201103":4.1,"201104":2.83,"201105":4.52,"201106":4.37,"201107":4.63,"201108":5.31,"201109":5.53,"201110":4.8,"201111":3.71,"201112":4.81,"201113":4.31,"201201":4.19,"201202":3.51,"201203":3.36,"201204":3.34,"201205":3.68,"201206":4.9,"201207":5.33,"201208":5.18,"201209":5.7,"201210":4.84,"201211":4.43,"201212":3.52,"201213":4.33,"201301":3.44,"201302":4.4,"201303":4.03,"201304":3.79,"201305":4.96,"201306":4.94,"201307":4.97,"201308":5.45,"201309":5.39,"201310":5.11,"201311":4.14,"201312":4.38,"201313":4.58,"201401":3.86,"201402":4.49,"201403":4.28,"201404":4.19,"201405":4.78,"201406":5.71,"201407":5.4,"201408":5.37,"201409":5.82,"201410":4.61,"201411":4.21,"201412":4.66,"201413":4.78,"201501":4.24,"201502":3.73,"201503":4.01,"201504":3.79,"201505":4.18,"201506":5.02,"201507":4.7,"201508":5.67,"201509":4.94,"201510":4.17,"201511":3.77,"201512":3.45,"201513":4.31,"201601":4.19,"201602":5.15,"201603":3.77,"201604":4.8,"201605":5.0,"201606":5.73,"201607":4.92,"201608":5.69,"201609":5.49,"201610":5.5,"201611":4.16,"201612":3.46,"201613":4.82,"201701":3.8,"201702":4.54,"201703":3.76,"201704":4.32,"201705":4.89,"201706":7.03,"201707":6.06,"201708":6.37,"201709":6.41,"201710":5.69,"201711":4.48,"201712":4.72,"201713":5.17,"201801":4.6,"201802":4.12,"201803":5.46,"201804":3.69,"201805":5.18,"201806":5.6,"201807":5.71,"201808":5.88,"201809":6.16,"201810":4.48,"201811":3.29,"201812":3.9,"201813":4.85,"201901":2.72,"201902":4.73,"201903":4.92,"201904":4.62,"201905":5.73,"201906":7.4,"201907":5.76,"201908":6.02,"201909":6.66,"201910":5.02,"201911":4.33,"201912":4.65,"201913":5.21,"202001":4.6,"202002":4.85,"202003":5.12,"202004":4.48,"202005":6.14,"202006":6.77,"202007":6.52,"202008":6.37,"202009":6.58,"202010":6.86,"202011":4.21,"202012":3.89,"202013":5.54}}},"header":{"title":"NASA/POWER CERES/MERRA2 Native Resolution Monthly and Annual","api":{"version":"v2.2.12","name":"POWER Monthly and Annual API"},"fill_value":-999.0,"start":"20010101","end":"20201231"},"messages":[],"parameters":{"ALLSKY_SFC_SW_DNI":{"units":"kW-hr/m^2/day","longname":"All Sky Surface Shortwave Downward Direct Normal Irradiance"}},"times":{"data":0.745,"process":0.02}};
const tempsByMonth = [null];
for(let [yearmonth, measurement] of Object.entries(data.properties.parameter.ALLSKY_SFC_SW_DNI)){
const month = extractMonth(yearmonth);
if(!tempsByMonth[month]) tempsByMonth[month] = 0;
tempsByMonth[month] = (tempsByMonth[month] + measurement)/2;
}
function extractMonth(yearmonth){
let month = yearmonth.substring(yearmonth.length-2);
return month.startsWith('0')? month[month.length-1] : month;
}
console.log(tempsByMonth);
console.log('Month with greatest value: ', tempsByMonth.indexOf(Math.max(...tempsByMonth)));
console.log('Month with lowest value: ', tempsByMonth.indexOf(Math.min(...tempsByMonth.filter(v=>v!==null))));
Given what you showed me, I just fixed a couple lines and you say that you understand the bubble database end of whatever you're doing so here's how to get your data from the api, but as for the months.. something strange, apparently there are 13 data points per year ;-;
Nonetheless, I'd just have a list of 13 averages instead of 12 due to the data I'm getting
let api_url="https://power.larc.nasa.gov/api/temporal/monthly/point?parameters=ALLSKY_SFC_SW_DNI&community=RE&longitude=48.0000&latitude=27.0000&format=JSON&start=2001&end=2020"
var list={} //will store data points on each month "number"
let response = await fetch(api_url)
let parseData = await response.json()
let interest=parseData.properties.parameter.ALLSKY_SFC_SW_DNI
for(const entry of Object.entries(interest)){
let [key,value]=entry //value is value xD
key=key.substring(4,6) //key becomes month "number"
list[key]=list[key]||{average:0,count:0}
list[key].count++; list[key].average+=value
}
Object.entries(list).forEach(([_,month])=>{
month.average/=month.count
})
console.log(list[12]) //sample of a month data
console.log(list) //full thing
Here's what it looks like

Javascript and HTML to display temperature and location from Yahoo API

Question
How can I build a minimal working sample on a site like codepen showing a location and it's temperature using the Yahoo weather API. I need specifically San Diego, CA. And using only HTML and Javascript, not PHP.
Background
I did check the site for a similar question but it only addressed temperature Getting only temperature from Yahoo Weather but it's only answer linked to an overcomplicated tutorial with excessive code.
Other answers on the site only have YML but don't show how to integrate an entire working example.
I was following along to the documentation from Yahoo but there is no working example like how NASA has a live example
Code
I have this CodePen demo
HTML
<div id="output"></div>
Javascript
$(document).ready(function () {
$.getJSON("https://query.yahooapis.com/v1/public/yql?q=select%20item.condition%20from%20weather.forecast%20where%20woeid%20%3D%202487889&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys/", function (data) {
console.log(data);
console.log(query)
$('#output').append( 'The temperature in' + result.location.["location"] + 'is' + result.condition.["temp"] );
})
})
Here's a working example based on your original code.
Something to note: you were doing this result.location.["location"] Which is invalid. You could use result.location["location"] or result.location.location (neither of which are returned in your result btw)
var queryURL = "https://query.yahooapis.com/v1/public/yql?q=select%20item.condition%20from%20weather.forecast%20where%20woeid%20%3D%202487889&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys/";
$.getJSON(queryURL, function (data) {
var results = data.query.results
var firstResult = results.channel.item.condition
console.log(firstResult);
var location = 'Unknown' // not returned in response
var temp = firstResult.temp
var text = firstResult.text
$('#output').append('The temperature is ' + temp + '. Forecast calls for '+text);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="output"></div>
Update
Your API query doesn't return location because you have it limited to select item.condition
Change q=select%20item.condition to q=select%20* andd you get a lot more data returned, including location.
Couple of things here:
You are trying to access the location and weather data incorrectly.
You should be using data.location and data.weather since you are
passing the JSON into the function as data in the function (data)
section.
Your API call is not being made properly. Review the documentation here and try to make the call again. https://developer.yahoo.com/weather/
This example does not have any excessive code and would be a great place to start: https://developer.yahoo.com/weather/#get-started
Based on the accepted answer I made one modification to account for the location. It's woeid has to be looked up using something like http://woeid.rosselliot.co.nz/ and then defined as a variable, in my case it was San Diego.
The resulting Javascript was
var queryURL = "https://query.yahooapis.com/v1/public/yql?q=select%20item.condition%20from%20weather.forecast%20where%20woeid%20%3D%202487889&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys/";
$.getJSON(queryURL, function (data) {
var results = data.query.results
var firstResult = results.channel.item.condition
console.log(firstResult);
var location = 'San Diego'
var temp = firstResult.temp
var text = firstResult.text
$('#output').append('The temperature in ' + location + ' is ' + temp + '. Forecast looks '+ text);
})
full working demo is at http://codepen.io/JGallardo/pen/XpBMRX

Is it possible to use JavaScript to track how many page views in past 24 hours?

I need to track how many users have visited some page in the past 24 hours, and if the number of users goes over 50 in this time, then I want to display the dynamically summed cumulative user count for that timeframe.
I have previously used a basic combination of JS POST and PHP parsing on the back end like this:
$.post( "//api.link.here/using.php", { someParameter: 'xxx' }, function(data) {
if(data > 50) {
$('#much-visits').html('Hot Like Fire: '+data);
}
});
But am now working on a platform that doesn't allow me to edit PHP in any way, and this method has not been developed on this platform.
The Question:
Is it possible to accomplish this same/similar thing but with javascript only (frameworks/outside API calls allowed)?
It's impossible to do it solely using client-side JavaScript, because then you wouldn't have any unified record of how many visitors came to the site. You must have either a server-side element or a third-party element (such as Google Analytics).
Actually, you can! You need jQuery though, so if you can get that, you're good to go!
Every time a person visits the page, execute this function (change usercount to something more unique):
$.ajax({
url:"http://count.io/vb/usercount/users+",
type: "POST"
});
And when you want to read its value, call this function. Usercount is the unique string you made previously:
$.ajax({
url:"http://count.io/vb/usercount/",
success: function(data) {
alert(data.counts[0].count);
}
});
It's important to know that if someone gets to know the string, they might be able to hack the system so be wary of that.
I figured out how to do this with the help of user kabiroberai's answer regarding count.io.
Every time a person visits the page, execute this function (change usercount to something more unique):
$.ajax({
url:"http://count.io/vb/usercount/users+",
type: "POST"
});
And when you want to read its value, call this function. Usercount is the unique string you made previously:
$.ajax({
url:"http://count.io/vb/usercount/",
success: function(data) {
alert(data.counts[0].count);
}
});
NOTE: It's important to know that if someone gets to know the string, they might be able to hack the system so be wary of that.
The problem with this method is that it gives us the total count of all time, rather than the count of users from the past 24 hours.
To get the 24-hour count, we can do this:
// Timestamp shim for browsers
// Timestamp
var timestamp = Math.floor(Date.now());
// 24 hour old timestampt
var dayAgo = timestamp - 86400000;
// Record a hit to the count.io DB under DankStopProduct# group, as a timestmped hit of 1
var productNumber = $('.some-product-element').find('some-unique-identifier').attr('value'); //Doesn't have to be value, could be any unique identifier
$.ajax({
url:'http://count.io/vb/YourProduct' + productNumber + '/' + timestamp + '+',
type: 'POST'
});
// Make dynamic HTTP prefix that depends on the prefi of the site's current page protocol
var httpPrefix = (window.location.protocol === 'http:' ? 'http:' : 'https:');
// Retrieve current product array
$.post(
//I use CORS-anywhere to retrieve the data as otherwise there is a cross-origin problem
httpPrefix + '//cors-anywhere.herokuapp.com/' + 'http://count.io/vb/YourProduct' + productNumber,
function (data) {
var timedViewCounter = 0;
var myStringArray = data.counts;
var arrayLength = myStringArray.length;
// Check each "timestamped hit" in the current product's array to see if it's older than 24 hours
for (var i = 0; i < arrayLength; i++) {
var itemTimestamp = data.counts[i].item;
// Count up all the product hits that are 24 hours old or newer
if (itemTimestamp > dayAgo) {
timedViewCounter++;
}
}
// If total count is greater than 50, then output HTML onto page
var hotItem = '<div id="hot-item"><strong><i class="fa fa-fire"></i> Hot Like Fire!</strong> - ' +
'<span class="view-count">' + timedViewCounter + '</span> people have viewed this product in the last 24 hours</div>';
if (timedViewCounter > 50) {
$(".FreeShippingContainer").before(hotItem);
}
});
And that's all! Now the product view count will only be output if it's 51 views or higher in the past 24 hours.

Bulk processing in mongo is very slow for 1 million records

Consider the following scenario:
CSV file is generated by a reporting tool every friday. It contains records for all the employees in the organisation (almost 1 million employees and increasing).
This data is saved in mongo using mongoimport in "Employee" Collection.
However, the requirement is to send "Welcome Mail" to new employees and "Year Completion Mail" to existing employees.
To solve this, I am importing the new file to a temporary collection("EmployeeTemp").
For every record in the temporary collection (EmployeeTemp), I check the old collection ("Employee"), for existing employees and mark "SendYearCompletionFlag" as true. Further, if a new employee record is found, I mark "SendWelcomeFlag" as true. Also, the project of each employee needs to be updated.
This complete process is executed via a script submitted to mongo.
The issue is that script is taking almost 18 hrs to complete.
Please help me to reduce the execution time of script.
This the script:
var list = db.employeeTemp.find().addOption(DBQuery.Option.noTimeout);
while(list.hasNext()){
var f = list.next();
var itr = db.employee.find({"eid":f.eid});
var obj = itr.hasNext() ? itr.next() : null;
if(!obj){
f.joiningDate = new Date();
f.sendWelcomeMail = true;
print("Saving New record : " + f.eid);
db.save(f);
} else {
var joinDate = obj.joiningDate;
if(new Date().getTime()-joinDate>=31536000000){
print("Sending Year Completion Mail to " + obj.eid)
obj.sendYearCompletionMail = true;
}
obj.projecct = f.project;
print("Saving Existing record : " + obj.eid);
db.save(obj);
}
}
I suggest you to create an index on employee.eid.
Another thing you can try is to change the batch size in the first find adding batchSize(500) after setting the no timeout option:
http://docs.mongodb.org/manual/reference/method/cursor.batchSize/

Modify JavaScript Object and use setRowsData to write to individual cell

I am using getRowsData to retrieve the information, but I would like to modify the values stored within a JS object and then write that modified value back into the cell. I would like to use the normalized header variable that was created with getRowsData to write back into the cell. So if I retrive the info using
var thirdEmployee = employeeObjects[2];
var stringToDisplay = "The third column is: " + thirdEmployee.firstName + " " + thirdEmployee.lastName;
stringToDisplay += " (id #" + thirdEmployee.employeeId + ") working in the ";
stringToDisplay += thirdEmployee.department + " department and with phone number ";
stringToDisplay += thirdEmployee.phoneNumber;
ss.msgBox(stringToDisplay);
Then, for example, I would assign a new value to the Javascript object thirdEmployee.phoneNumber; and then have it written into the proper location in the range (i.e., active row, column # based on header).
thirdEmployee.phoneNumber = "123-555-5555";
thirdEmployee.phoneNumber.setNewValue();
or
setNewValue.thirdEmployee.phoneNumber;
Basically, it would be a modified version of setRowsData but allow for modification of one object and then telling that object to be written into the spreadsheet based on the active row & column based on the header.
Anyone use or know how to do this?
The setRowsData() helper function from the Writing Data from JavaScript Objects to a Spreadsheet tutorial already supports the ability to write a single object. To use it, though, you need to provide both of the optional parameters optHeadersRange and optFirstDataRowIndex.
If we assume that your headers are in row 1, here's how you could update thirdEmployee:
var headersRange = sheet.getRange(1, 1, 1, sheet.getLastColumn());
var thirdEmployee = employeeObjects[2];
...
thirdEmployee.phoneNumber = "123-555-5555";
setRowsData(sheet, [thirdEmployee], headersRange, 3 );

Categories