Javascript variable being overwriiten after query execution - javascript

I am using mysql database with Nodejs. I am running a query like this:
rows = await pool.query(`Select partID,stageID,locationID,QuantityAfter, QuantityChange, rowDeleted from InventoryTransactions
where partID = ${item.partID} and stageID = ${item.stageID} and locationID = ${item.locationID} and orderID = ${orderID}
order by transactionID desc`)
if(rows[0].rowDeleted != 1){ //This means that the quantity in the inventory table and inv trans table is not the same
console.log(`=====================================`)
console.log(Number(rows[0].QuantityChange))
console.log(Number(rows[0].QuantityChange))
console.log(Number(rows[0].QuantityChange))
await pool.query(`Insert into inventorytransactions(OrderID,PartID,LocationID,StageID,QuantityBefore,QuantityChange,QuantityAfter,ITTTimeStamp,rowDeleted,id)
Values(${orderID},${rows[0].partID},${rows[0].locationID},${rows[0].stageID},${parseInt(rows[0].QuantityAfter)},${-parseInt(rows[0].QuantityChange)},${parseInt(rows[0].QuantityAfter)-parseInt(rows[0].QuantityChange)},'${(new Date ((new Date((new Date(new Date())).toISOString() )).getTime() - ((new Date()).getTimezoneOffset()*60000))).toISOString().slice(0, 19).replace('T', ' ')}',true,${id})`)
console.log(Number(rows[0].QuantityChange))
console.log(Number(rows[0].QuantityChange))
console.log(Number(rows[0].QuantityChange))
console.log(`Update inventory set Quantity = quantity - ${Number(rows[0].QuantityChange)} where partID =${rows[0].partID} and stageID = ${rows[0].stageID} and locationID = ${rows[0].locationID}`)
await pool.query(`Update inventory set Quantity = quantity - ${Number(rows[0].QuantityChange)} where partID =${rows[0].partID} and stageID = ${rows[0].stageID} and locationID = ${rows[0].locationID} `)
console.log(`=====================================`)
}
The reason I have so many console.log is because I have encountered a very weird bug. All of the values of rows[0].QuantityChange) should be the same.
But my console shows:
====================================
4
4
4
425
NaN
NaN
NaN
Update inventory set Quantity = quantity - NaN where partID =12462 and stageID = 1 and locationID = 1
{ Error: ER_BAD_FIELD_ERROR: Unknown column 'NaN' in 'field list'
I know 425 is the value of ${id} variable which can be found at the end of the insert sql statement. Which makes no sense to me. What makes even less sense is how are the the bottom values are undefined or NAN

The 425 likely comes from some other code that is running during your await pool.query() statement (not from anything in the code you show us). await blocks the execution of the local function, but it does not block the event queue so other events can run while an await ... is waiting for completion.
Then, you don't show where rows is defined, but it seems possible that it's getting overwritten by some other code that is running during the await. If you show us a lot more context around this code including where rows is defined, we could advise and explain in more detail.

I'm not sure, but, in this part
'${(new Date ((new Date((new Date(new Date())).toISOString() )).getTime() - ((new Date()).getTimezoneOffset()*60000))).toISOString().slice(0, 19).replace('T', ' ')}'
Exist an incorrect use of single quotes, which can be altering the result of the consult. You should scape inner single quotes, or use Double quotes for wrapping the complete instruction.
"${(new Date ((new Date((new Date(new Date())).toISOString() )).getTime() - ((new Date()).getTimezoneOffset()*60000))).toISOString().slice(0, 19).replace('T', ' ')}"

Related

Collection Boolean isn't being set to false - Meteor

So in short, the app that i'm developing is a bus timetable app using Meteor, as a practice project.
inside my body.js, I have an interval that runs every second, to fetch the current time and compare to items in a collection.
To show relevant times, I have added an isActive boolean, whenever the current time = sartTime of the collection, it sets it to true, and that is working fine.
But when I do the same thing for endTime and try to set it to false, so I can hide that timeslot, it just doesn't work. Even consoles don't show up. What am I missing? I have recently just started doing meteor, so excuse the redundancies.
Worth noting that the times that I'm comparing to are times imported from an CSV file, so they have to be in the 00:00 AM/PM format.
Thank you guys so much for your time.
Body.js code:
Template.Body.onCreated(function appBodyOnCreated() {
Meteor.setInterval(() => {
var h = (new Date()).getHours();
const m = ((new Date()).getMinutes() <10?'0':'') + ((new Date()).getMinutes());
var ampm = h >= 12 ? ' PM' : ' AM';
ampmReac.set(ampm);
if (h > 12) {
h -= 12;
} else if (h === 0) {
h = 12;
}
const timeAsAString = `${h}${m}`;
const timeAsAStringFormat = `${h}:${m}`;
whatTimeIsItString.set(timeAsAStringFormat + ampm); // convert to a string
const timeAsANumber = parseInt(timeAsAString); // convert to a number
whatTimeIsIt.set(timeAsANumber); // update our reactive variable
if (Timetables.findOne({TimeStart: whatTimeIsItString.get()}).TimeStart == whatTimeIsItString.get())
{
var nowTimetable = Timetables.findOne({TimeStart: whatTimeIsItString.get() });
Timetables.update({_id : nowTimetable._id },{$set:{isActive : true}});
console.log('I am inside the START statement');
}
else if (Timetables.findOne({TimeEnd: whatTimeIsItString.get()}).TimeEnd == whatTimeIsItString.get())
{
var nowTimetable = Timetables.findOne({TimeEnd: whatTimeIsItString.get() });
Timetables.update({_id : nowTimetable._id },{$set:{isActive : false}});
console.log('I am inside the END statement');
}
}, 1000); //reactivate this function every second
});
})
Very probably it is just that your if / else blocks does what you ask it:
It tries to find a document in Timetables, with specified TimeStart. If so, it makes this document as "active".
If no document is previously found, i.e. there is no timeslot which TimeStart is equal to current time, then it tries to find a document with specified TimeEnd.
But your else if block is executed only if the previous if block does not find anything.
Therefore if you have a next timeslot which starts when your current timeslot ends, your if block gets executed for that next timeslot, but the else if block is never executed to de-activate your current timeslot.
An easy solution would be to transform your else if block in an independent if block, so that it is tested whether the previous one (i.e. TimeStart) finds something or not.
Ok so I got it to work eventually. My problem was that it was never going to the second IF statement.
What I have done is set up a whole new Meteor.interval(() >) function, and placed that second IF in there, as is.
I think the problem was that it was it checks the first IF statement and gets stuck there, no matter what the outcome of the parameters is.

A string of form nnnn-nnnn is displayed in a spreadsheet as a date or otherwise incorrectly

I have a script I have been using in my test environment to programmically create a tracking number by parsing the year from timestamp and padding the response index.
function setTrackingNumber(ss, lastRowInx, createDateColumn) //This block generates and stores a tracking number in Column AU on the backend
{
var padTrackNo = "" + lastRowInx;
var trackSize = 4;
var trackingNumberColumn = createDateColumn-3; //trackingNumberColumn is currently in AU (Column 47) Calculating using it's relative position to createDateColumn Position
if (ss.getRange(lastRowInx, trackingNumberColumn).getValue() == "") // so that subsequent edits to Google Form don't overwrite original tracking number
{
if (padTrackNo > trackSize)
{
var padTrackNo = pad(padTrackNo, trackSize);
}
else {} //do nothing
var shortYear = setShortYear(ss, lastRowInx, createDateColumn);
var trackingNumber = shortYear + "-" + padTrackNo;
var createTrackingNumber = ss.getRange(lastRowInx, trackingNumberColumn);
createTrackingNumber.setValue(trackingNumber);
}
else {} //should do nothing
return;
}//This is the end of the setTrackingNumber function
function setShortYear(ss, lastRowInx, createDateColumn)
{
var newCreateDate = ss.getRange(lastRowInx,createDateColumn).getValue();
var strDate = "" + newCreateDate;
var splitDate = strDate.split(" ");
var trimYear = splitDate[3];
var shortYear = trimYear;
return shortYear;
}//This is the end of the shortYear function
function pad(padTrackNo, trackSize)
{
while (padTrackNo.length < trackSize)
{
padTrackNo = "0"+padTrackNo;
}
return padTrackNo;
}//This is the end of pad function
That gets me test result which is as expected ex. 2016-0005. However when we added it to another production sheet it seemed to work with test data and then production data showed up like a date 3/1/2016. production result - first cell.
I thought it must just be formatting the string as a date because of the numbers so I tried formatted the column as plain text but that just changed the date to a plain text version of the date.
I thought this might be similar to needing to specify the format like I did in this question Appending initial timestamp from Google Form to end of record in order to permanently store create date onFormSubmit at #SandyGood 's suggestion so I tried setting the number format as [0000-0000] by changing
createTrackingNumber.setValue(trackingNumber);
to
createTrackingNumber.setValue(trackingNumber).setNumberFormat("0000-0000");
which resulted in the [production result - second cell] which again doesn't match the expected result.
Oddly, some submissions seem to work just fine like [production result - third cell]. Over the past 3 days and approximately 10 records it has been fine, then hinky, then fine, they hinky, then fine again. I am not really sure what else to try to debug this odd behaviour.
Note: I had to parse the date as a string as I was having trouble getting it to parse the date correctly from the create date which is taken from initial timestamp.
To my understanding, "2016-0005" is not a number but a string, so the cell containing it should be formatted as plain text. With a script, this can be done by
range.setNumberFormat('#STRING#')
(source), and this must be done before you set the value to the cell. Like this:
createTrackingNumber.setNumberFormat('#STRING#').setValue(trackingNumber);

Query Instagram posts by hashtag and time range

I'm trying to query posts from Instagram by providing the hashtag and the time range (since and until dates).
I use the recent tags endpoint.
https://api.instagram.com/v1/tags/{tag-name}/media/recent?access_token=ACCESS-TOKEN
My code is written in Node.js using the instagram-node library (see the inline comments):
// Require the config file
var config = require('../config.js');
// Require and intialize the instagram instance
var ig = require('instagram-node').instagram();
// Set the access token
ig.use({ access_token: config.instagram.access_token });
// We export this function for public use
// hashtag: the hashtag to search for
// minDate: the since date
// maxDate: the until date
// callback: the callback function (err, posts)
module.exports = function (hashtag, minDate, maxDate, callback) {
// Create the posts array (will be concated with new posts from pagination responses)
var posts = [];
// Convert the date objects into timestamps (seconds)
var sinceTime = Math.floor(minDate.getTime() / 1000);
var untilTime = Math.floor(maxDate.getTime() / 1000);
// Fetch the IG posts page by page
ig.tag_media_recent(hashtag, { count: 50 }, function fetchPosts(err, medias, pagination, remaining, limit) {
// Handle error
if (err) {
return callback(err);
}
// Manually filter by time
var filteredByTime = medias.filter(function (currentPost) {
// Convert the created_time string into number (seconds timestamp)
var createdTime = +currentPost.created_time;
// Check if it's after since date and before until date
return createdTime >= sinceTime && createdTime <= untilTime;
});
// Get the last post on this page
var lastPost = medias[medias.length - 1] || {};
// ...and its timestamp
var lastPostTimeStamp = +(lastPost.created_time || -1);
// ...and its timestamp date object
var lastPostDate = new Date(lastPostTimeStamp * 1000);
// Concat the new [filtered] posts to the big array
posts = posts.concat(filteredByTime);
// Show some output
console.log('found ' + filteredByTime.length + ' new items total: ' + posts.length, lastPostDate);
// Check if the last post is BEFORE until date and there are no new posts in the provided range
if (filteredByTime.length === 0 && lastPostTimeStamp <= untilTime) {
// ...if so, we can callback!
return callback(null, posts);
}
// Navigate to the next page
pagination.next(fetchPosts);
});
};
This will start fetching the posts with the most recent to least recent ones, and manually filter the created_time.
This works, but it's very very inefficient because if we want, for example, to get the posts from one year ago, we have to iterate the pages until that time, and this will use a lot of requests (probably more than 5k / hour which is the rate limit).
Is there a better way to make this query? How to get the Instagram posts by providing the hashtag and the time range?
I think this is the basic idea you're looking for. I'm not overly familiar with Node.js, so this is all in plain javascript. You'll have to modify it to suit your needs and probably make a function out of it.
The idea is to convert an instagram id (1116307519311125603 in this example) to a date and visa versa to enable you to quickly grab a specific point in time rather then backtrack through all results until finding your desired timestamp. The portion of the id after the underscore '_' should be trimmed off as that refers, in some way, to the user IIRC. There are 4 functions in the example that I hope will help you out.
Happy hacking!
//static
var epoch_hour = 3600,
epoch_day = 86400,
epoch_month = 2592000,
epoch_year = 31557600;
//you'll need to set this part up/integrate it with your code
var dataId = 1116307519311125603,
range = 2 * epoch_hour,
count = 1,
tagName = 'cars',
access = prompt('Enter access token:'),
baseUrl = 'https://api.instagram.com/v1/tags/' +
tagName + '/media/recent?access_token=' + access;
//date && id utilities
function idToEpoch(n){
return Math.round((n / 1000000000000 + 11024476.5839159095) / 0.008388608);
}
function epochToId(n){
return Math.round((n * 0.008388608 - 11024476.5839159095) * 1000000000000);
}
function newDateFromEpoch(n){
var d = new Date(0);
d.setUTCSeconds(n);
return d;
}
function dateToEpoch(d){
return (d.getTime()-d.getMilliseconds())/1000;
}
//start with your id and range; do the figuring
var epoch_time = idToEpoch(dataId),
minumumId = epochToId(epoch_time),
maximumId = epochToId(epoch_time + range),
minDate = newDateFromEpoch(epoch_time),
maxDate = newDateFromEpoch(epoch_time + range);
var newUrl = baseUrl +
'&count=' + count +
'&min_tag_id=' + minumumId +
'&max_tag_id=' + maximumId;
//used for testing
/*alert('Start: ' + minDate + ' (' + epoch_time +
')\nEnd: ' + maxDate + ' (' + (epoch_time +
range) + ')');
window.location = newUrl;*/
To support this excellent answer, an instagram ID is generated via the plpgSQL function:
CREATE OR REPLACE FUNCTION insta5.next_id(OUT result bigint) AS $$
DECLARE
our_epoch bigint := 1314220021721;
seq_id bigint;
now_millis bigint;
shard_id int := 5;
BEGIN
SELECT nextval('insta5.table_id_seq') %% 1024 INTO seq_id;
SELECT FLOOR(EXTRACT(EPOCH FROM clock_timestamp()) * 1000) INTO now_millis;
result := (now_millis - our_epoch) << 23;
result := result | (shard_id << 10);
result := result | (seq_id);
END;
$$ LANGUAGE PLPGSQL;
from Instagram's blog
Despite a similar getting posts process, Data365.co Instagram API, I currently working at, seems to be more suitable and efficient. It does not have a limit of 5,000 posts per hour, and you can specify the period of time for which your need posts in the request itself. Also, the billing will be taken into account only posts from the indicated period. You won't have to pay for data you don't need.
You can see below a task example to download posts by the hashtag bitcoins for the period from January 1, 2021, to January 10, 2021.
POST request: https://api.data365.co/v1.1/instagram/tag/bitcoins/update?max_posts_count=1000&from_date=2021-01-01&to_date=2021-01-10&access_token=TOKEN
A GET request example to get the corresponding list of posts:
https://api.data365.co/v1.1/instagram/tag/bitcoins/posts?from_date=2021-01-01&to_date=2021-01-10&max_page_size=100&order_by=date_desc&access_token=TOKEN
More detailed info view in API documentation at https://api.data365.co/v1.1/instagram/docs#tag/Instagram-hashtag-search

Postgresql9.3 query optimization

I am using postgresql 9.3 in my node.js application. In my database i have some 7lakhs records now. Also in my database i have json datatype column.
My query is as following:
EXPLAIN ANALYSE select id_0, name_0, id_1, name_1, id_2, name_2, id_3, name_3, id_4, name_4, latitude, longitude, to_char(collecteddate, 'dd/mm/yyyy') as collecteddate, key, value->>'xxxxx' as value from table where
CAST(value->'xxxxx'->> 'aaaaa' as INTEGER)BETWEEN 1 and 43722 and value->'PCA_2011'->> 'aaaaa' NOT LIKE ' ' and
CAST(value->'xxxxx'->> 'bbbbb' as INTEGER)BETWEEN 1 and 100 and value->'xxxx'->> 'bbbbb' NOT LIKE ' '
and leveltype = 'nnnn' and id_1= 'ww' and id_0 = 'uuu' and collecteddate = '2011-03-31';
This query will retrieve almost 1lakh records and takes 3 secs to be executed. I have created index for the json column and also the columns in where conditions. But i think its very long time to execute. Is there any way to reduce the execution time. I am new to this database optimization concepts, is there any optimization techniques to reduce my execution time to some milli seconds. Thanks in advance..
EDIT:
My index definition:
CREATE INDEX index_pop on table (id_0, id_1, collecteddate, leveltype, key, (value->'xxxxx'->>'aaaa'));
My Explain analyses result:
"Bitmap Heap Scan on table (cost=1708.27..59956.46 rows=1 width=132) (actual time=880.576..5137.266 rows=93615 loops=1)"
" Recheck Cond: (((id_0)::text = '356'::text) AND ((id_1)::text = '9'::text) AND (collecteddate = '2011-03-31'::date) AND ((leveltype)::text = 'pppp'::text))"
" Filter: ((((value -> 'xxxx'::text) ->> 'aaaa'::text) !~~ ' '::text) AND (((value -> 'xxxxx'::text) ->> 'bbbb'::text) !~~ ' '::text) AND ((((value -> 'xxxxx'::text) ->> 'aaaaa'::text))::integer >= 1) AND ((((value -> 'PCA (...)"
" Rows Removed by Filter: 4199"
" -> Bitmap Index Scan on index_name (cost=0.00..1708.27 rows=37856 width=0) (actual time=828.856..828.856 rows=97814 loops=1)"
" Index Cond: (((id_0)::text = '356'::text) AND ((id_1)::text = '9'::text) AND (collecteddate = '2011-03-31'::date) AND ((leveltype)::text = 'ppppp'::text))"
"Total runtime: 5211.271 ms"
ALso 1 more thing: Bitmap Index Scan on index_name is different index other than in my where condition index, also y only 1 index is earched??

MongoDB MapReduce, Date and % operator

I have a problem with a python-script witch i use to aggregate large collections into smaller pieces and have them grouped by a timestamp.
map = Code("function(number) {"
"emit({"
"ts : new Date(new Date((this.ts - (this.ts % (60 * number))) * 1000).setSeconds(0))"
"}, 1);"
"}")
reduce = Code("function(key, vals) {"
"var sum = 0;"
"for (var i in vals) {"
"sum += vals[i]"
"}"
"return sum;"
"}")
As you can see, it's a pretty simple MapReduce and the timestamp (ts) should be grouped by anny given number of minutes. I've tested the Javascript here http://jsfiddle.net/QgMzK/1/ and it seems to work fine. But when i run it in Python all timestamps become ISODate("1970-01-01T00:00:00Z").
Any ideas?
Your map function takes one parameter: number, which, when called by map-reduce, will be set to null and after coertion (and some % by zero) will make the date your map is returning ISODate("0NaN-NaN-NaNTNaN:NaN:NaNZ"). This after type conversion becomes datetime.datetime(1970, 1, 1, 0, 0).
Remove the parameter and it should work.
edit
To confirm that, try running this code:
from pymongo import Connection
from bson.code import Code
db = Connection().mr_test
for i in xrange(10):
db.things.insert({"x" : i})
map = Code("function(number) {"
"emit({"
"ts : number"
"}, 1);"
"}")
reduce = Code("function(key, vals) {"
"var sum = 0;"
"for (var i in vals) {"
"sum += vals[i]"
"}"
"return sum;"
"}")
result = db.things.map_reduce(map, reduce, "test_results")
for doc in result.find():
print doc
The result on my machine is :
{u'_id': {u'ts': None}, u'value': 10.0}
Note that ts is None in the result, cause number was not set when the mapping function executed.
edit 2
AFAIK the only way to pass a parameter to map is by using scope optional parameter in map_reduce, but then you'll have to remove it from map signature anyway.
So by changing your map to:
map = Code("function() {"
"emit({"
"ts : new Date(new Date((this.ts - (this.ts % (60 * number))) * 1000).setSeconds(0))"
"}, 1);"
"}")
and by calling:
db.whatever.map_reduce(map, reduce, "collection_name", scope = {"number" : the_value_your_function_needs})
you can get the result you want.

Categories

Resources