I built a working node.js Express app using the tutorial "Deploy Express.js to Azure App Service using Visual Studio Code", see:
https://learn.microsoft.com/en-us/azure/developer/javascript/tutorial/deploy-nodejs-azure-app-service-with-visual-studio-code?tabs=bash.
This first version was deployed and worked successfully using only Get requests.
I made some minor changes to include Post requests and deployed that update. This takes 18 minutes to deploy, but the new version is not served to my browser, just the old version. Going to my Azure dashboard and clicking my app service and selecting Browse there, it still shows the old version 2 days after the successful update deploy.
Another problem is that after a long time, say overnight, a request to the app's api does not get answered. My Safari browser says the server stopped responding. But a second request immediately after does get a response, but still with the same old version.
This JSON file may be useful.
{
"id": "/subscriptions/3603adff-9823-408c-980c-ea71f06376ce/resourceGroups/AcesTraderExpress-rg/providers/Microsoft.Web/sites/AcesTraderExpress",
"name": "AcesTraderExpress",
"type": "Microsoft.Web/sites",
"kind": "app,linux",
"location": "East US",
"properties": {
"name": "AcesTraderExpress",
"state": "Running",
"hostNames": [
"acestraderexpress.azurewebsites.net"
],
"webSpace": "AcesTraderExpress-rg-EastUSwebspace-Linux",
"selfLink": "https://waws-prod-blu-217.api.azurewebsites.windows.net:454/subscriptions/3603adff-9823-408c-980c-ea71f06376ce/webspaces/AcesTraderExpress-rg-EastUSwebspace-Linux/sites/AcesTraderExpress",
"repositorySiteName": "AcesTraderExpress",
"owner": null,
"usageState": 0,
"enabled": true,
"adminEnabled": true,
"enabledHostNames": [
"acestraderexpress.azurewebsites.net",
"acestraderexpress.scm.azurewebsites.net"
],
"siteProperties": {
"metadata": null,
"properties": [
{
"name": "LinuxFxVersion",
"value": "NODE|14-lts"
},
{
"name": "WindowsFxVersion",
"value": null
}
],
"appSettings": null
},
"availabilityState": 0,
"sslCertificates": null,
"csrs": [],
"cers": null,
"siteMode": null,
"hostNameSslStates": [
{
"name": "acestraderexpress.azurewebsites.net",
"sslState": 0,
"ipBasedSslResult": null,
"virtualIP": null,
"thumbprint": null,
"toUpdate": null,
"toUpdateIpBasedSsl": null,
"ipBasedSslState": 0,
"hostType": 0
},
{
"name": "acestraderexpress.scm.azurewebsites.net",
"sslState": 0,
"ipBasedSslResult": null,
"virtualIP": null,
"thumbprint": null,
"toUpdate": null,
"toUpdateIpBasedSsl": null,
"ipBasedSslState": 0,
"hostType": 1
}
],
"computeMode": null,
"serverFarm": null,
"serverFarmId": "/subscriptions/3603adff-9823-408c-980c-ea71f06376ce/resourceGroups/AcesTraderExpress-rg/providers/Microsoft.Web/serverfarms/AcesTraderExpress-plan",
"reserved": true,
"isXenon": false,
"hyperV": false,
"lastModifiedTimeUtc": "2021-11-24T21:28:18.1666667",
"storageRecoveryDefaultState": "Running",
"contentAvailabilityState": 0,
"runtimeAvailabilityState": 0,
"siteConfig": {
"numberOfWorkers": 1,
"defaultDocuments": null,
"netFrameworkVersion": null,
"phpVersion": null,
"pythonVersion": null,
"nodeVersion": null,
"powerShellVersion": null,
"linuxFxVersion": "NODE|14-lts",
"windowsFxVersion": null,
"requestTracingEnabled": null,
"remoteDebuggingEnabled": null,
"remoteDebuggingVersion": null,
"httpLoggingEnabled": null,
"azureMonitorLogCategories": null,
"acrUseManagedIdentityCreds": false,
"acrUserManagedIdentityID": null,
"logsDirectorySizeLimit": null,
"detailedErrorLoggingEnabled": null,
"publishingUsername": null,
"publishingPassword": null,
"appSettings": null,
"metadata": null,
"connectionStrings": null,
"machineKey": null,
"handlerMappings": null,
"documentRoot": null,
"scmType": null,
"use32BitWorkerProcess": null,
"webSocketsEnabled": null,
"alwaysOn": false,
"javaVersion": null,
"javaContainer": null,
"javaContainerVersion": null,
"appCommandLine": null,
"managedPipelineMode": null,
"virtualApplications": null,
"winAuthAdminState": null,
"winAuthTenantState": null,
"customAppPoolIdentityAdminState": null,
"customAppPoolIdentityTenantState": null,
"runtimeADUser": null,
"runtimeADUserPassword": null,
"loadBalancing": null,
"routingRules": null,
"experiments": null,
"limits": null,
"autoHealEnabled": null,
"autoHealRules": null,
"tracingOptions": null,
"vnetName": null,
"vnetRouteAllEnabled": null,
"vnetPrivatePortsCount": null,
"publicNetworkAccess": null,
"cors": null,
"push": null,
"apiDefinition": null,
"apiManagementConfig": null,
"autoSwapSlotName": null,
"localMySqlEnabled": null,
"managedServiceIdentityId": null,
"xManagedServiceIdentityId": null,
"keyVaultReferenceIdentity": null,
"ipSecurityRestrictions": null,
"scmIpSecurityRestrictions": null,
"scmIpSecurityRestrictionsUseMain": null,
"http20Enabled": false,
"minTlsVersion": null,
"scmMinTlsVersion": null,
"ftpsState": null,
"preWarmedInstanceCount": null,
"functionAppScaleLimit": 0,
"healthCheckPath": null,
"fileChangeAuditEnabled": null,
"functionsRuntimeScaleMonitoringEnabled": null,
"websiteTimeZone": null,
"minimumElasticInstanceCount": 0,
"azureStorageAccounts": null,
"sitePort": null
},
"deploymentId": "AcesTraderExpress",
"slotName": null,
"trafficManagerHostNames": null,
"sku": "Free",
"scmSiteAlsoStopped": false,
"targetSwapSlot": null,
"hostingEnvironment": null,
"hostingEnvironmentProfile": null,
"clientAffinityEnabled": true,
"clientCertEnabled": false,
"clientCertMode": 0,
"clientCertExclusionPaths": null,
"hostNamesDisabled": false,
"domainVerificationIdentifiers": null,
"customDomainVerificationId": "32CA73F9034F12CA2A538C5F30E96A3BDF81DFD04981F8BFE65F69C4E24A69E6",
"kind": "app,linux",
"inboundIpAddress": "20.49.104.15",
"possibleInboundIpAddresses": "20.49.104.15",
"ftpUsername": "AcesTraderExpress\\$AcesTraderExpress",
"ftpsHostName": "ftps://waws-prod-blu-217.ftp.azurewebsites.windows.net/site/wwwroot",
"outboundIpAddresses": "40.76.167.202,52.146.70.44,52.146.70.103,52.146.68.209,52.146.68.246,52.146.69.57,20.49.104.15",
"possibleOutboundIpAddresses": "40.76.167.202,52.146.70.44,52.146.70.103,52.146.68.209,52.146.68.246,52.146.69.57,52.146.70.115,52.146.70.118,52.146.70.158,52.146.66.148,52.146.71.5,40.76.165.150,40.76.167.156,40.76.167.157,52.146.68.142,52.146.64.68,52.146.65.22,52.146.65.23,52.191.239.27,52.191.239.78,52.191.239.120,52.224.200.31,52.224.201.90,52.224.202.78,20.49.104.15",
"containerSize": 0,
"dailyMemoryTimeQuota": 0,
"suspendedTill": null,
"siteDisabledReason": 0,
"functionExecutionUnitsCache": null,
"maxNumberOfWorkers": null,
"homeStamp": "waws-prod-blu-217",
"cloningInfo": null,
"hostingEnvironmentId": null,
"tags": null,
"resourceGroup": "AcesTraderExpress-rg",
"defaultHostName": "acestraderexpress.azurewebsites.net",
"slotSwapStatus": null,
"httpsOnly": false,
"redundancyMode": 0,
"inProgressOperationId": null,
"geoDistributions": null,
"privateEndpointConnections": [],
"buildVersion": null,
"targetBuildVersion": null,
"migrationState": null,
"eligibleLogCategories": "AppServiceAppLogs,AppServiceAuditLogs,AppServiceConsoleLogs,AppServiceHTTPLogs,AppServiceIPSecAuditLogs,AppServicePlatformLogs,ScanLogs",
"storageAccountRequired": false,
"virtualNetworkSubnetId": null,
"keyVaultReferenceIdentity": "SystemAssigned"
}
}
I am following this website. Initially I am added only Get request and deployed to azure portal using this doc Deploy Node.js Express.js to App Service from Visual Studio Code - Azure | Microsoft Docs.
(Note: Skipped the Local git deployment process).
Directly deployed using Deploy to Web app in Visual Studio Code
Then, I am adding the below code in visual studio with Post Request
Add below code in app.js
const express = require("express");
const port = process.env.PORT || 3000
const bodyParser = require("body-parser")
// App using express node module
const app = express();
app.use(bodyParser.urlencoded({
extended:true
}));
// Get request
app.get("/", function(req, res) {
res.sendFile(__dirname + "/index.html");
});
// Post Request
app.post("/", function(req, res) {
var num1 = Number(req.body.num1);
var num2 = Number(req.body.num2);
var result = num1 + num2 ;
res.send("Addition - " + result);
});
app.listen(port, function(){
console.log('server is running on port 3000');
})
Added the below code in index.html
< !DOCTYPE html>
< html lang="en" dir="ltr">
< head>
< meta charset="utf-8">
< title>Calculator</title>
< /head>
< body>
< h1>Simple Calculator.< /h1>
< form action="/" method="post">
< input type="text" name="num1" placeholder="First Number">
< input type="text" name="num2" placeholder="Second Number">
< button type="submit" name="submit">
calculator
< /button>
< /form>
< /body>
< /html>
After added Post Method request, I was deployed again in a Azure Web App. (By Default it was deployed in Linux app service).
I can view the results in Browser
I am trying to build a JSON with NodeJS and SQL result.
The database is:
CREATE TABLE category (
id int(10) unsigned NOT NULL AUTO_INCREMENT,
title varchar(255) NOT NULL,
parent_id int(10) unsigned DEFAULT NULL,
PRIMARY KEY (id),
FOREIGN KEY (parent_id) REFERENCES category (id)
ON DELETE CASCADE ON UPDATE CASCADE
);
CREATE TABLE `items` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`cat_id` int unsigned DEFAULT NULL,
`parent_id` int unsigned DEFAULT NULL,
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
PRIMARY KEY (`id`),
KEY `cat_id` (`cat_id`),
KEY `sub_id` (`parent_id`),
CONSTRAINT `cat_id` FOREIGN KEY (`cat_id`) REFERENCES `category` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `sub_id` FOREIGN KEY (`parent_id`) REFERENCES `category` (`parent_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
BEGIN;
INSERT INTO `category` VALUES (1, 'Colazione', NULL);
INSERT INTO `category` VALUES (2, 'Pranzo', NULL);
INSERT INTO `category` VALUES (3, 'Primi piatti', 2);
INSERT INTO `category` VALUES (4, 'Second dish', 2);
INSERT INTO `category` VALUES (5, 'Other things for lunch', 2);
COMMIT;
-- ----------------------------
-- Records of items
-- ----------------------------
BEGIN;
INSERT INTO `items` VALUES (1, 1, NULL, 'Cornetto');
INSERT INTO `items` VALUES (2, 3, 2, 'Pasta al sugo 1');
INSERT INTO `items` VALUES (3, 3, 2, 'Pasta al sugo 2');
INSERT INTO `items` VALUES (4, 3, 2, 'Pasta al sugo 3');
INSERT INTO `items` VALUES (5, 3, 2, 'Pasta al sugo 1 X');
INSERT INTO `items` VALUES (6, 3, 2, 'Pasta al sugo 2 X');
INSERT INTO `items` VALUES (7, 4, 2, 'Pasta al sugo 3 X');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
The expected JSON is:
Category:
Sub-Categories:
Items:
If category doesn't got any sub-categories it will print:
Category:
Items:
We got more than one categories and each categories can have more than one sub-categories.
Each sub-categories can have more than one item.
How can I build a JSON result with NodeJS with SQL Query?
Expected JSON:
{
"menu": {
"categories": [
{
"id_category": 1,
"category_title": "Colazione",
"items": [
{
"id_item": 1,
"title": "Cornetto"
}
]
},
{
"id_category": 2,
"category_title": "Pranzo",
"subcategories": [
{
"title_subcategories": "Primi piatti",
"items": [
{
"id_item": 1,
"title": "Pasta al sugo 1"
},
{
"id_item": 2,
"title": "Pasta al sugo 2"
}
]
},
{
"title_subcategories": "Secondi piatti",
"items": [
{
"id_item": 1,
"title": "Pasta al sugo 3"
}
]
}
]
}
]
}
}
Here's what I came up with, although I haven't tested it:
async function buildJson(categories, items) {
// `query` is some function that queries the DB
const categries = await query('SELECT id AS id_category, title AS category_title, parent_id FROM categories');
const items = await query('SELECT id AS id_item, title AS item_title, cat_id FROM items');
const data = {
menu: {
categories: [],
},
};
const subcategories = categories.filter(category => category.parent_id !== null);
categories.filter(category => category.id_parent === null)
.forEach(category => {
data.menu.categories.push({
id_category: category.id_category,
category_title: category.category_title,
});
data.menu.categories.forEach(_category => {
_category.items = items.filter(item => item.cat_id === _category.id_category)
.map(item => ({
id_item: item.id_item,
title: item.title,
}));
_category.subcategories = categories.filter(__category => __category.parent_id === _category.id);
_category.subcategories.forEach(subcategory => {
subcategory.items = items.filter(item => item.cat_id === subcategory.id_category)
.map(item => ({
id_item: item.id_item,
title: item.title,
}));
});
});
});
return data;
}
I have quite a lot of data in JSON files that I need to convert to the SQLite database. I did a simple loop with the INSERT query, but the queries take a lot of time. I am a hobbyist and I am learning all the time. I think that there must be a more professional solution.
use JSON::XS;
use DBI;
my $CCC = 'string';
# start connection to SQLite
my $dbh = DBI->connect(
"dbi:SQLite:dbname=aaaa.db", "", "", { RaiseError => 1 }, ) or die $DBI::errstr;
my $stmt = "CREATE TABLE IF NOT EXISTS $CCC (id INTEGER PRIMARY KEY AUTOINCREMENT, start INTEGER UNIQUE, open REAL NOT NULL, high REAL NOT NULL, low REAL NOT NULL, close REAL NOT NULL, vwp REAL NOT NULL, volume REAL NOT NULL, trades INTEGER NOT NULL)";
my $sth = $dbh->prepare( $stmt );
my $rv = $sth->execute() or die $DBI::errstr;
if($rv < 0) {
print $DBI::errstr;
}
# Open file.json
open(my $fh, '<', file.json) or die "cannot open file";
{
local $/;
$data = <$fh>;
}
# Converting JSON format to Perl's variables
my $coder = JSON::XS->new->ascii->pretty->allow_nonref;
my $json = $coder->decode ($data);
# Loop. Im inserting every hash ({}) from file.json by INSERT sql statement
foreach (#{$json}) {
my $stmt = "INSERT OR IGNORE INTO $CCC values (null, strftime('%s',\'$_->{T}\'), $_->{O}, $_->{H}, $_->{L}, $_->{C}, ".(($_->{H}+$_->{L}+$_->{C}+$_->{O}) / 4).", $_->{V}, 1)";
my $sth = $dbh->prepare( $stmt );
my $rv = $sth->execute() or die $DBI::errstr;
if($rv < 0) {
print $DBI::errstr;
}
}
file.json
[{"O": 1.0, "H": 1.0, "L": 0.00014, "C": 0.000145, "V": 176703.92394752, "T": "2018-02-16T00:00:00", "BV": 25.71390226}, {"O": 0.00014499, "H": 0.00014499, "L": 0.00011101, "C": 0.00012599, "V": 247646.2068748, "T": "2018-02-16T00:05:00", "BV": 30.66246148}, {"O": 0.00012599, "H": 0.0001295, "L": 0.000122, "C": 0.00012699, "V": 102563.86201627, "T": "2018-02-16T00:10:00", "BV": 12.88322597}]
Do you know any more efficient way?
I think you should have the statement and prepare outside the foreach loop (using placeholders), then execute inside the loop. The prepare normally only needs to be done once.
foreach (#{$json}) {
my $stmt = "INSERT OR IGNORE INTO $CCC values (null, strftime('%s',\'$_->{T}\'), $_->{O}, $_->{H}, $_->{L}, $_->{C}, ".(($_->{H}+$_->{L}+$_->{C}+$_->{O}) / 4).", $_->{V}, 1)";
my $sth = $dbh->prepare( $stmt );
my $rv = $sth->execute() or die $DBI::errstr;
if($rv < 0) {
print $DBI::errstr;
}
}
Perhaps this:
my $stmt = "INSERT INTO $CCC values (?, ?, ?, ?, ?, ?, ?, ?, ?)";
my $sth = $dbh->prepare( $stmt );
foreach (#{$json}) {
$sth->execute(undef, $_->{T}, $_->{O}, $_->{H}, $_->{L}, $_->{C}, ($_->{H}+$_->{L}+$_->{C}+$_->{O}) / 4, $_->{V}, 1) or die $DBI::errstr;
}
Update: placed undef as first parameter as suggested by Kjetil S.