How to access variable outside then promise function? - javascript

I have used Sequelize with mysql database in my node js application. I want to fetch the value from the db and passed in to the bash script, consider the following code email is fetched from db and stored it in variable but I couldn't access outside of then function
desc users;
+------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | YES | | NULL | |
| value | varchar(255) | YES | | NULL | |
| created_at | datetime | NO | | NULL | |
| updated_at | datetime | NO | | NULL | |
+------------------+--------------+------+-----+---------+----------------+
6 rows in set (0.24 sec)
code:
User.findOne({where: {name: 'name'}}).then(function(user) {
var name = user.value
});
User.findOne({where: {name: 'email'}}).then(function(user) {
var email = user.value
});
User.findOne({where: {name: 'age'}}).then(function(user) {
var value = user.value
});
var child = exec('bash user.sh name age email')
How to access variables (name, email, age) outside then function in node js?

var child = exec('bash user.sh email')
User.findOne({where: {name: 'usr1'}}).then(function(user) {
var email = user.email;
console.log(child);
},child);

The database query runs asynchronously, So if you want to use any result from the query, you must write that code inside then.
For example -
User.findOne({where: {name: 'usr1'}})
.then(function(user) {
// Do your stuff here.
var email = user.email;
var child = exec('bash user.sh email');
});

The most intuitive solution would be to use async await
(async () => {
const email = await User.findOne({where: {name: 'usr1'}});
const child = exec('bash user.sh email');
})();

Related

DISTINCT on results of a knex.js INNER JOIN

I have two tables, metadata and view_events. Both metadata and view_events have config_id and config_type columns. I'm trying to select all view_events for a given user email, distinct by config_id and config_type, ordered by timestamp, desc, and limited to the 10 most recent. The following knex.js code isn't working but hopefully expresses what I'm trying to achieve:
return dbClient<AuthenticatedUserIndexRow>(METADATA_TABLE_NAME)
.select([
`${METADATA_TABLE_NAME}.${METADATA_COLUMNS.CONFIG_ID}`,
`${METADATA_TABLE_NAME}.${METADATA_COLUMNS.CONFIG_TYPE}`,
`${METADATA_TABLE_NAME}.${METADATA_COLUMNS.DESCRIPTION}`,
`${VIEW_EVENTS_TABLE_NAME}.${VIEW_EVENTS_COLUMNS.TIMESTAMP}`,
])
.innerJoin<AuthenticatedUserIndexRow>(VIEW_EVENTS_TABLE_NAME, function innerJoinOnViewEvents() {
this.on(
`${METADATA_TABLE_NAME}.${METADATA_COLUMNS.STORAGE_ID}`,
'=',
`${VIEW_EVENTS_TABLE_NAME}.${VIEW_EVENTS_COLUMNS.CONFIG_STORAGE_ID}`,
)
.andOn(
`${VIEW_EVENTS_TABLE_NAME}.${VIEW_EVENTS_COLUMNS.USER_EMAIL}`,
'=',
rawSql('?', [authUserEmail]),
)
.andOn(`${METADATA_TABLE_NAME}.${METADATA_COLUMNS.DELETED}`, '=', rawSql('?', [false]));
})
.distinct([
`${METADATA_TABLE_NAME}.${METADATA_COLUMNS.CONFIG_TYPE}`,
`${METADATA_TABLE_NAME}.${METADATA_COLUMNS.CONFIG_ID}`,
])
.limit(EVENT_LIMIT)
.orderBy(VIEW_EVENTS_COLUMNS.TIMESTAMP, 'desc');
For example, given the following tables:
view_events
+-------------+-----------+--------------------------+----------------------+
| config_type | config_id | timestamp | email |
+-------------+-----------+--------------------------+----------------------+
| a | foo | 2020-01-23T03:08:14.618Z | john.smith#gmail.com |
| a | foo | 2020-01-23T03:08:14.500Z | jane.doe#gmail.com |
| a | foo | 2020-01-23T03:08:13.618Z | john.smith#gmail.com |
| a | bar | 2020-01-23T03:08:12.618Z | john.smith#gmail.com |
| a | foo | 2020-01-23T03:08:11.618Z | john.smith#gmail.com |
| b | foo | 2020-01-23T03:08:10.618Z | john.smith#gmail.com |
| a | baz | 2020-01-23T03:08:09.618Z | john.smith#gmail.com |
| a | foo | 2020-01-23T03:08:08.618Z | john.smith#gmail.com |
+-------------+-----------+--------------------------+----------------------+
metadata
+-------------+-----------+---------------------------+
| config_type | config_id | description |
+-------------+-----------+---------------------------+
| a | foo | Type a config with id foo |
| a | bar | Type a config with id bar |
| b | foo | Type b config with id foo |
| a | baz | Type a config with id baz |
+-------------+-----------+---------------------------+
I am trying to obtain the following output (given an authUserEmail of john.smith#gmail.com):
+-------------+-----------+---------------------------+
| config_type | config_id | description |
+-------------+-----------+---------------------------+
| a | foo | Type a config with id foo |
| a | bar | Type a config with id foo |
| b | foo | Type b config with id foo |
| a | baz | Type a config with id baz |
+-------------+-----------+---------------------------+
I'm not a SQL expert, but am generally aware that the use of SELECT and DISTINCT together here doesn't work. What's the correct approach?
Does the following roughly work for you? I did using with as so we could grab the 10 most recent configs (max(timestamp)..group by config) and then remove the timestamp column in the final projection. Note the final records may not appear in exact timestamp order as you did not want timestamp in your final output, but they will be the 10 most recent. I haven't added the DELETED column but imagine you will re-add that based on the code in your question.
knex.with('ordered_items', (qb) =>
qb.table('metadata')
.innerJoin('view_events', function() {
this.on('metadata.config_id', '=', 'view_events.config_id')
.andOn('metadata.config_type', '=', 'view_events.config_type')
})
.where({'view_events.email': 'john.smith#gmail.com'})
.select(['metadata.config_type', 'metadata.config_id',
'metadata.description'])
.max('view_events.timestamp', {as: 'max_ts'})
.groupBy(['metadata.config_id', 'metadata.config_type', 'metadata.description'])
.orderBy('max_ts', 'desc')
.limit(10))
.table('ordered_items')
.select(['config_type', 'config_id', 'description'])
My input and output:
sqlite> select * from metadata;
a|foo|Type a config with id foo
a|bar|Type a config with id bar
b|foo|Type b config with id foo
a|baz|Type a config with id baz
sqlite> select * from view_events;
a|foo|2020-01-23T03:08:14.618Z|john.smith#gmail.com
a|foo|2020-01-23T03:08:14.500Z|jane.doe#gmail.com
a|foo|2020-01-23T03:08:13.618Z|john.smith#gmail.com
a|bar|2020-01-23T03:08:12.618Z|john.smith#gmail.com
a|foo|2020-01-23T03:08:11.618Z|john.smith#gmail.com
b|foo|2020-01-23T03:08:10.618Z|john.smith#gmail.com
a|baz|2020-01-23T03:08:09.618Z|john.smith#gmail.com
a|foo|2020-01-23T03:08:08.618Z|john.smith#gmail.com
[ { config_type: 'a',
config_id: 'foo',
description: 'Type a config with id foo' },
{ config_type: 'a',
config_id: 'bar',
description: 'Type a config with id bar' },
{ config_type: 'b',
config_id: 'foo',
description: 'Type b config with id foo' },
{ config_type: 'a',
config_id: 'baz',
description: 'Type a config with id baz' } ]

Nested Json response from NodeJs and MySql

I have 3 Mysql tables, a vendor table with a list of vendors, a categories table with a list of categories that these vendors have in there stores, the categories table is linked to to the vendors table with a secondary key(vendor_id), i also have a product table that has all the products in these categories and it is linked to the category table using a foreign key (category_id). How do i write a NodeJs/ express route that returns a json object that looks like this,
{
"id": 1,
"vendor": "Food place",
"category": "Chicken"[
{
"id": "1,
"name": "Fried chicken",
"price": "100"
},
{
"id": "2,
"name": "Soup Chicken",
"price": "150"
}
}
So the json object returns a vendor all the categories they have in there store, and inside the categories all the products that be long to these categories
The tables look similar to this
Vendor table:
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| category | varchar(255) | NO | | NULL | |
+----------+--------------+------+-----+---------+----------------+
Category table:
+-----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(20) | YES | | NULL | |
| vendor_id | int(11) | NO | MUL | NULL | |
+-----------+-------------+------+-----+---------+----------------+
Product table:
+-----------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+---------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| price | decimal(10,0) | NO | | NULL | |
| name | varchar(255) | YES | | NULL | |
| category_id | int(11) | YES | MUL | NULL | |
+-----------------+---------------+------+-----+---------+----------------+
Route
export const route = (router: any) => {
return router.get('/your_route_here', (req: any, res: any) => {
// do your logic here
});
}
export default route;

Unknown column 'created_at' in 'field list

Here is my customer_schema.js file:
up () {
this.create('customers', (table) => {
table.increments()
table.string('name', 30)
})
}
CustomerSeed.js:
class CustomerSeeder {
async run () {
const customer = await Factory
.model('App/Models/Customer')
.create()
console.log('customer: ')
}
}
The Customer.js model is "empty "
I run the migrations, all is Ok, but can not run the seeds : adonis seed throws this error message:
code: 'ER_BAD_FIELD_ERROR',
errno: 1054,
sqlMessage: "Unknown column 'created_at' in 'field list'",
sqlState: '42S22',
index: 0,
sql:
"insert into `customers` (`created_at`, `name`, `updated_at`) values ('2019-03-04 20:01:17', 'Peter Walsh', '2019-03-04 20:01:17')" }
Why this happens? I did not even declare table.timestamps() in my schema file and :
describe customers;
+-------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(30) | YES | | NULL | |
+-------+------------------+------+-----+---------+----------------+
2 rows in set (0.01 sec)
Edit:
static get createdAtColumn () {
return null;
}
static get updatedAtColumn () {
return null;
}
Add this 2 functions to your model, it should work :)
To add to the previous good answer, when you have lot of models as the application grows, you can automate the above solution instead of writing it as per model:
'use strict'
class NoTimestamp {
register (Model) {
Object.defineProperties(Model, {
createdAtColumn: {
get: () => null,
},
updatedAtColumn: {
get: () => null,
},
})
}
}
module.exports = NoTimestamp
Credit to Romain Lanz who showed me this solution.

AlaSQL nested arrays

I'm trying tu use the AlaSQL Array agregator inside an array, it appears to be not supported :(
Trying to acomplish this output (or like this):
[
{
"keyword":"project 1",
"projects": [
{
"year":2014,
"description":"this is a project description",
"budget": 5600,
"status": "closed",
"metadata": [
{
"key":"provider",
"value":"just me"
},
{
"key":"client",
"value":"someone"
},
{
"key":"any thing",
"value":"any data..."
}
]
}
]
}
]
My Database Structure
people e
| name | type |
|-----------|---------|
| name | varchar |
| lastname | varchar |
| person_id | varchar |
| cel | int |
projects p
| name | type |
|-------------|---------|
| keyword | varchar |
| year | int |
| description | text |
| budget | int |
PeopleProjects x
| name | type |
|-------------|---------|
| e_person_id | varchar |
| p_keyword | varchar |
| p_year | int |
| status | varchar |
metadata m
| name | type |
|-------------|---------|
| e_person_id | varchar |
| p_keyword | varchar |
| p_year | int |
| key | varchar |
| value | varchar |
My query
alasql("SELECT p.keyword, \
ARRAY({year:p.year, description:p.description, budget:p.budget, status:x.status, \
ARRAY({key:m.key, value:m.value}) as metadata \
}) AS projects \
FROM projects p, PeopleProjects x, metadata m \
WHERE \
p.keyword = x.p_keyword AND x.p_keyword = m.p_keyword AND \
p.year = x.p_year AND x.p_year = m.p_year \
x.e_person_id = x.e_person_id AND AND x.e_person_id = 2 \
GROUP BY p.keyword");
At the moment, I divided the query in two and then combine the data to produce the hole thing.
Any ideas?
I managed to get the output I want by fetching two times:
First, projects:
var projects = alasql("SELECT p.keyword, ARRAY({status:x.status, year:p.year, description:p.description, budget:p.budget }) AS years \
FROM PeopleProjects x, projects p \
WHERE x.p_keyword = p.keyword AND x.p_year = p.year AND x.e_person_id = "+person_id+" \
GROUP BY p.keyword");
Second, metadata:
var mdata = alasql("SELECT m.e_person_id, m.p_keyword, m.p_year, ARRAY({key:m.key,value:m.value}) as [metadata] \
FROM metadata m, PeopleProjects x \
WHERE x.e_person_id = m.e_person_id AND x.p_keyword = m.p_keyword AND x.p_year = m.p_year AND x.e_person_id = "+person_id+" \
GROUP BY m.e_person_id, m.p_keyword, m.p_year");
Then, loop over projects, searching and storing the metadata:
for(i=0;i<projects.length;i++){
for(j=0;j<projects[i].years.length;j++){
current = projects[i].keyword;
current_year = projects[i].years[0].year;
search = alasql("SEARCH / * WHERE(year="+current_year+" AND keyword='"+current+"') FROM ?",[mdata]);
projects[i].years[j]["metadata"] = search[0].metadata;
}
}
Now projects has all the data.
Any suggestion will be welcome.

ER_BAD_FIELD_ERROR when using Waterline ORM in Sails.js

I'm getting the following error when trying to call .create() on a model from a Sails.js controller.
Here is my model, TemperatureReading.js:
module.exports = {
connection: 'mainDatabase',
tableName: 'TemperatureReading',
attributes: {
id: {
columnName: 'id',
type: 'integer',
minLength: 1,
primaryKey: true,
unique: true
},
deviceId: {
columnName: 'deviceId',
type: 'integer',
minLength: 1,
},
temperatureReading: {
columnName: 'temperatureReading',
type: 'string',
max: 150,
required: true
},
dateRecorded: {
columnName: 'dateRecorded',
type: 'string',
},
}
};
routes.js:
module.exports.routes = {
'get /enterSensorReading': 'MainController.getSensorReading'
};
MainController.getSensorReading:
getSensorReading: function (request, response) {
var temperatureReading = request.param('temperatureReading');
var date = new Date();
var dateRecorded = date.getDate() + "/"
+ (date.getMonth()+1) + "/"
+ date.getFullYear() + " "
+ date.getHours() + ":"
+ date.getMinutes() + ":"
+ date.getSeconds();
console.log(temperatureReading);
TemperatureReading.create({temperatureReading: temperatureReading, dateRecorded: dateRecorded}).exec(function(err, createdReading) {
if(err) {
response.send(err);
} else {
console.log('Created reading');
}
});
}
connections.js
module.exports.connections = {
mainDatabase: {
adapter: 'sails-mysql',
host: '127.0.0.1',
port: 3306,
user: 'myUser',
password: 'myPW',
database: 'MAIN'
}
};
And finally, my database structure:
TemperatureReading
------------------
id int(5) PK
deviceId int(5)
temperatureReading varchar(255)
date varchar(255)
Any ideas as to what is going wrong?
The database structure should be something like this:
mysql> describe TemperatureReading;
+--------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| deviceId | int(11) | YES | | NULL | |
| temperatureReading | varchar(255) | YES | | NULL | |
| dateRecorded | varchar(255) | YES | | NULL | |
| createdAt | datetime | YES | | NULL | |
| updatedAt | datetime | YES | | NULL | |
+--------------------+--------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
It should be dateRecorded and not just date
If its a new app and you are creating the table from scratch, use add "migrate": "drop" in your model. This will automatically create the table for you. Make sure to remove this line next time you lift the server. If this does not solve the problem, then I don't see any issue with the code. I tested and it worked perfectly on my system. It might be possible that something messed up with your sails-mysql adapter. If fixing your database structure does not solve the problem, try this
npm uninstall sails-mysql
npm cache clear
npm install sails-mysql
Even more rigorous way would be:
rm -Rf node_modules
npm cache clear
npm install
Let me know if this solves the problem you are facing

Categories

Resources