Better way to do this with Node.js, Express, and MySQL? - javascript

So I was wondering if anyone had a better method for my problem. Basically I want a record inside a record that I'm inserting into a database. What I mean is, I need to have a history of all the changes made to the record when updated. So whenever the record is updated, I save the info in a "Updates" column. Every time theres an update, I select the updates from that record, concatenate the new info onto the old updates and inserting it. See my code below.
app.post("/updateRecord", function(req,res){
var prevResultUpdates = "";
async function first(){
con.query("SELECT * FROM Equipment WHERE Serial="+req.body.serial+" AND Part="+req.body.part, function(err,result,fields){
if (err) throw err;
console.log(result[0]['Updates'])
return prevResultUpdates= prevResultUpdates + "," + result[0]['Updates']
});
}
async function second(){
await first();
var customer = req.body.customer;
var update = "\'" + prevResultUpdates + ',' + req.body.update + "," + Number(Date.now()) + "," + req.body.customer + ',' +"\'";
var serial = req.body.serial;
var part = req.body.part;
var sql="Update `Equipment` SET `Customer`= '"+customer+"', `Updates`="+update+" WHERE Serial=" + serial + " AND Part=" + part;
con.query(sql,function(err,result,fields){
if (err) throw err;
res.json(result)
})
}
second();
res.end()
})
Any thoughts on how to do this better?

A bunch of suggestions here.
First, put a column in your table like this:
last_change TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
It will always contain the time of the most recent INSERT or UPDATE operation on each row, automatically without you needing to mention it in your SQL.
Second, be aware that
UPDATE Equipment SET Updates = Updates + ' some text string'
works. You can change a column in place, without fetching its former value. But, this can fail when the column gets too long. So, do this instead.
UPDATE Equipment SET Updates = RIGHT(Updates + ' some text string', 255)
assuming your Updates column is defined as VARCHAR(255). I used RIGHT() rather than LEFT() because presumably the most recent update is the most interesting.
Third, you'd probably be wise to normalize this, to add an Equipment_history table. Instead of appending your update log to a column, insert a new row into Equipment_history. That table might have these columns
equipment_history_id INT primary key
equipment_id INT foreign key to Equipment table
customer VARCHAR(255) identity of the customer
update VARCHAR(255) reason for update
last_change TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
This lets you reconstruct the history of your updates if need be.

Related

Javascript append some calculation results into table rows one by one

I'm working on a simple electron / node.js app, which takes input information locally, do some calculation and present calculation results in a table
Input:
10s of rows of features info
ID | length | depth |
Calculation: takes about seconds for each feature calculation.
Output:
Some amount of row from input, but with a results column
ID | length | depth | Results
I tried to append the results to tables for presenting, the code looks like this
<table id = 'results-table'>
<th>ID</th><th>length</th><th>depth</th><th>Results</th>
</table>
function getCrackTableValues(){
document.body.style.cursor = 'wait';
var table = document.getElementById('input-table'); //get info from input table
for (var r = 1, n = table.rows.length; r < n; r++) { //skip table head tart from second row
const crackID = table.rows[r].cells[0].innerHTML; //input
var a_m = Number(table.rows[r].cells[1].innerHTML); // input
var c_m = Number(table.rows[r].cells[2].innerHTML); //input
var result = foo(a_m, c_m); //foo just for example, takes seconds for calculation
var newRow = document.getElementById('results-table').insertRow(); //output table
newRow.innerHTML = '<td>'+ crackID+
'</td><td>' + `${a_m.toFixed(1)}` +
'</td><td>' + `${c_m.toFixed(1)}` +
'</td><td>' + `${result.toFixed(1)}` + //append results to output table
'</td>';
}
document.body.style.cursor = 'default';
}
The code works ok, but with couple issues.
Q1: I was hoping once a single calculation is done, it will show results on the output table, and move to next entry's calculation. So the user could see current results, while the calculation of the rest rows are going on.
Currently it seems the output table won't show up until all the calculations are done.
Are there any ways I could use to make the results table grows/shows up one by one, as calculation of each row goes on?
Q2: I was trying to disable the cursor while the calculation goes on document.body.style.cursor = 'wait';. and enable the cursor back on after all calculations are done.
But it seems this line executed after calculation, it would just disabled the cursor and flash back on.
Are there any potential issue with my current implementation? My node.js is v12.16.3, on a old 32bit windows 7.
The cause of both issues is the same: the UI won't get chance to update until it manages to escape your very-long-running loop.
You need to change foo() to become an async function. You've not shown any details, so I will assume it is pure CPU calculation and has no file or network access points.
I think I'd first pull out the loop contents into another function. And then I've put the loop termination condition at the top of that new function:
function processOneRow(r){
const table = document.getElementById('input-table');
if(r >= table.rows.length){ //All done
document.body.style.cursor = 'default';
return;
}
const crackID = table.rows[r].cells[0].innerHTML;
const a_m = Number(table.rows[r].cells[1].innerHTML);
const c_m = Number(table.rows[r].cells[2].innerHTML);
const result = foo(a_m, c_m);
const newRow = document.getElementById('results-table').insertRow();
newRow.innerHTML = '<td>'+ ...;
setTimeout(processOneRow, 0, r+1)
}
And then you can start it going by calling it for the first row:
function getCrackTableValues(){
document.body.style.cursor = 'wait';
setTimeout(processOneRow, 0, 1)
}
The use of setTimeout() with a 0ms delay, gives the UI thread time to update each time, before it will call processOneRow() on the next row of the input table.
Aside: Putting the code to restore the cursor inside processOneRow() is a bit of a code smell. If this code was going in a library, I would probably use before()/after() hooks. (You could then also make sure the after() hook gets called if there is an exception thrown.)
The other way to approach this would be to use worker threads and move the foo(a_m, c_m) calculation there. That would then naturally be async. Beyond the extra complexity, the downside of that is if foo() uses data, it needs to be kept with it in that worker thread, which gets complex if the same data is needed in the main thread. But, otherwise, it is a better solution for long running processes.

Inserting multiple entries in collection

I am attempting to create barcodes that increment by 1 for an entered quantity and add each of them to a MongoDB collection.
I use db.controlNumber.insert({controlNumber}) to do this, and I also use
console.log(controlNumber) to see my result. However, in the database, the incremented number will go to the max and enter that many times, where the console.log shows it increment.
while (i < count) {
i++;
controlNumber.controlNumber = controlVar[0] + "-" + controlVar[1] + "-" +
controlVar[2] + "-" + controlVar[3] + "-000" + i;
db.controlNumber.insert(controlNumber);
console.log(controlNumber);
}
I expect my mongoDB collection to have control number (for example if user wants 5 control numbers)
a-b-c-d-001
a-b-c-d-002
...
a-b-c-d-005
Instead, it makes 5 entries of
a-b-c-d-005
You're mutating controlNumber.controlNumber. Instead, create a new object to insert:
const toInsert = Object.assign({}, controlNumber, { controlNumber: i });
db.controlNumber.insert(toInsert)
It'd likely also be worth either using async/await or promises to handle asynchronous calls. If you do await db.controlNumber.insert(controlNumber) you wouldn't have run into any problems because it would have waited for the document to be fully inserted before moving on to the next one.

How to I use my firebase variables as an integer?

I have a simple program that you can post/accept games then report back the score. I am having an issue of updating the score as information stored in firebase is stored as a string. How do I take my score as an integer to add to it?
if (selfScore > oppScore) {
var ref = new Firebase('taken out');
var selfRef = firebase.database().ref("users/" + (selfKey));
selfRef.update({
"tScore": ("tScore" + 3)
});
}
Ideally, the score would take the previous score and add 3 but this is not the case. I'm new to firebase so if this is obvious, my bad. An edit to clarify when I remove tscore and just have tScore: +3 it just changes tScore to 3, it doesn't add it.
You cannot make some operations on field value within the update() method. So you should first read the value from the database and then update the record with the new value.
The best approach is to use a transaction for such operation, which will automatically do the read/write operation and, in addition, ensure "there are no conflicts with other clients writing to the same location at the same time".
You would then do as follows:
var selfRef = firebase.database().ref("users/" + selfKey + "/tScore");
selfRef.transaction(function(currentValue) {
return currentValue + 3;
});

ExtJS 5.0 - override to provide custom ordering on a grid column

A grid control column is ordering based on name which is a combined field of first + ' ' + last. The client wants to order by last + ', ' + first. I am not permitted to change the existing code, can only use overrides.
Based on the results of web searching, I think using sortType to transform the input value is the least intrusive approach. But I'm not sure how to plug it in.
I think sortType works on data fields, so in an initComponent overload can I get access to what I need? For example, this is how I override in the view to change the rendering:
initComponent: function() {
this.callParent([]);
this.columns[0].renderer =
function(value, metaData, record, rowIdx, colIdx, store, view) {
var result = '';
if (!Ext.isEmpty(record.data) && !Ext.isEmpty(record.data.details)) {
var details = record.data.details;
// value == details.name is 'first last', won't be using that
result = details.last + ', ' + details.first;
}
return result;
};
}
Can I get access to the details.name definition from here to override sortType? Will agree that this isn't the best approach, because I'll have to do some parsing of name to split it and then stick it back together. And that's going to have issues for those with multiple first and/or last names.
An alternate approach is to overload doSort but if I don't have access to details.first and details.last, it won't be any better than sortType. I saw one example of implementing doSort and it looks very complicated. Does anyone know of some detailed documentation for doSort?
The problem is that sortType does not take the whole record, and it is applied directly to columns[0].dataIndex, without any possibility to interfere. And you can only use string manipulation if you are sure where first name ends and last name starts:
this.columns[0].sortType = function(value) {
var spl = value.split(' ');
return value[1] + ', ' + value[0];
}
Of course this will run into issues with Names like "Carl Friedrich Theodor Wilhelm Freiherr von und zu Guttenberg" and the like, even "George W. Bush" would be an issue.
The better way is to introduce another field into the model, something along the lines of
MyApp.model.Resource.getFields().push(Ext.create('Ext.data.Field',{
name:"LastFirst",
convert:function(v,rec) {
return rec.get("last")+', '+rec.get("first")
}
}));
This change does not affect existing model instances, so you would have to do it before any model instance is created.
This would allow you to set columns[0].dataIndex="LastFirst", scrap the renderer change, and also get useful sorting.
It is difficult to give some code or a stub, but i found some answers about ordering. As i know ext 4 have sortType on a stores. So what you actually need is to create custom sortType to your store (and to create a store if you haven`t it yet).
Ext have ways to order things in a grid, use initComponent for other stuff.
sortType looks like this

getJSON on Sharepoint list stops at 1000

$.getJSON("urlhere", {}, function(data)
{
// Other code is commented out, I'm just using the following loop to test.
for(var a = 0; a < 2546; a++)
if(a > 995)
alert((a + 1) + ": " + data.d.results[a].Column2);
});
For some reason, I wasn't getting all the things from my list that I needed. So I put in this loop to test it and it stops at 1000 for some reason. Why does this happen and how do I fix it?
SharePoint only returns 1000 results per "page." If you look, there should be a "link" element in there near the bottom of the JSON that contains a link to the next 1000 results.
That's how it is when it returns XML, anyway. Haven't tried JSON, but I'm sure it's similar.
'urlForListData' + '?$filter=Building eq \'' + building + '\''
I found out that you can filter the list for what you need so that it never exceeds 1000, which was much simpler than what I was doing before. Of course, Building is a column in the SharePoint list and building is a variable holding the requested building number.

Categories

Resources