Create a dynamic Mysql Insert from an Object - mysql

I have a project in Typescript in which I am trying to create an Insert through the options that I send through an object. Right now I have two objects, one for each Insert, these Inserts are created in different tables and with different objects. I would like to know if it is possible to create a general Insert for several objects.
This is what I currently have:
let object1 = [
{ country: 'CO', name: 'CO_SE.xml', exists: 1 },
{ country: 'CO', name: 'CO_IN.xml', exists: 1 },
{ country: 'CO', name: 'CO_BR.xml', exists: 1 }
];
`INSERT INTO ${database} VALUES` + object1.map((elem: any) =>
`"${elem.country}", "${elem.name}", ${elem.exists})`).join(', ');
let object2 = [
{ code: 1, folder: '/ToFtp', max: 8 },
{ code: 2, folder: '/ToXml', max: 5 },
{ code: 3, folder: '/ToMail', max: 5 }
];
`INSERT INTO ${database} VALUES` + object2.map((elem: any) =>
`${elem.code}, "${elem.folder}", ${elem.max})`).join(', ');
This is what I am trying to achieve:
let object1 = [
{ country: 'CO', name: 'CO_SE.xml', exists: 1 },
{ country: 'CO', name: 'CO_IN.xml', exists: 1 },
{ country: 'CO', name: 'CO_BR.xml', exists: 1 }
];
let object2 = [
{ code: 1, folder: '/ToFtp', max: 8 },
{ code: 2, folder: '/ToXml', max: 5 },
{ code: 3, folder: '/ToMail', max: 5 }
];
`INSERT INTO ${database} VALUES` + ${object}.map((elem: any) =>
`"${elem.elem1}", ... ${elem.elemN})`).join(', ');
Is this possible? I'm not sure this can be done.

You can create methods to prepare your query and values. You can do something like this.
let object1 = [
{ country: 'CO', name: 'CO_SE.xml', exists: 1 },
{ country: 'CO', name: 'CO_IN.xml', exists: 1 },
{ country: 'CO', name: 'CO_BR.xml', exists: 1 }
];
function getValues<T extends Record<string, any>[]>(obj: T) {
const values = obj.map((item) => {
const val = Object.values(item).map((v) => v);
return val;
});
return values;
}
function getColumns<T extends Record<string, any>>(obj: T) {
return Object.keys(obj);
}
function getFilters<T extends Record<string, any>>(obj: T) {
const constraints: string[] = [];
const queryArray: any[] = [];
Object.entries(obj).forEach(([k, v]) => {
constraints.push(`${k} = ?`);
queryArray.push(v);
});
return {
constraints,
queryArray
}
}
const columns = getColumns(object1[0]);
const values = getValues(object1);
const sql = `INSERT INTO MyTable(${columns.join(", ")}) VALUES ?`;
const filters = {
country: "CO"
};
const selectFilters = getFilters(filters);
const selectSql = `SELECT ${columns} FROM MyTable WHERE ${selectFilters.constraints.join(" AND ")}`;
console.log(columns); // [ 'country', 'name', 'exists' ]
console.log(sql); // INSERT INTO MyTable(country, name, exists) VALUES ?
console.log(values); // [ [ 'CO', 'CO_SE.xml', 1 ], [ 'CO', 'CO_IN.xml', 1 ], [ 'CO', 'CO_BR.xml', 1 ] ]
// now you can use something like this
connection.query({ sql, values });
Note: Make sure you sanitize your input before using these functions to avoid any damage you may create if your input is not as you are expecting it.

Related

Sequlize bulkCreate with updateOnDuplicates return all values(duplicated and not duplicated)

I have this code
const users = await User.bulkCreate(newUsers, {
updateOnDuplicate: ['name'],
});
Its query return all values in response like
[
{
id:1,
name: 'Andrew'
},
{
id:2,
name: 'John'
},
{
id:3,
name: 'Andrew'
},
]
But in database that query writes only unique value. Only 1 Andrew and 1 John.
I need to return only 2 records not 3

trying to group by artist using Sequelize and NodeJs

I have a simple Mysql table like the following fields:
Id, songName, ArtistName, siglosID
example data:
1 My Way Frank Sinatra 1
2 Big Balls ACDC 2
3 New York Frank Sinatra 3
4 Highway To Hell ACDC 4
I want to return an object to return to graphql where data is grouped by artistName
something like the following:
[ artistName: 'ACDC':[
{ id: 2, songName: 'Big Balls', artistName: 'ACDC', siglosId: '2' },
{ id: 4, songName: 'Highway To Hell', artistName: 'ACDC', siglosId: '4' },],
[ artistName: 'Frank Sinatra':[
{ id: 3, songName: 'New York', artistName: 'Frank Sinatra', siglosId: '3' },
{ id: 1, songName: 'My Way', artistName: 'Frank Sinatra', siglosId: '1' },],
]
What I actually get back:
[
{ id: 2, songName: 'Big Balls', artistName: 'ACDC', siglosId: '2' },
{
id: 1,
songName: 'My Way',
artistName: 'Frank Sinatra',
siglosId: '1'
}
Not sure how to use group properly or do I need to use a join?
My code:
getAllSongs: {
type: new GraphQLList(SongType),
async resolve() {
const mytest = await dbSong.findAll({
order: ["artistName"],
group: ["artistName"],
raw: true,
});
console.log("test Songs grouped by artist: ", mytest);
// return dbSong.findAll({ raw: true });
return dbSong.findAll({
order: ["artistName"],
group: ["artistName"],
raw: true,
});
},
},
},
});`

Run a MySQL query on the result of another MySQL query, then push the result of that query into a new array (NodeJS)

I have this function
export const classPerformance = async (req, res) => {
const { classID } = req.body;
db.query(
"SELECT u.userID FROM userIndex u LEFT JOIN classStudent cs ON cs.studentID = u.userID WHERE cs.classID = ?;",
[classID],
(err, result) => {
if (err) {
res.status(500).send("Something went wrong...");
} else {
let parentArr = [
{
user: result,
},
];
let newArr = [];
const dataFetch = parentArr.forEach((data) => {
data.user.forEach((user) => {
db.query(
`SELECT
u.userID AS 'studentID',
u.firstName AS 'firstName',
u.lastName AS 'lastName',
(SELECT COUNT(completionStatus) FROM pacesetterEntries WHERE studentID = ? AND classID = ? AND completionStatus = 'Completed') AS 'Completed',
COUNT(completionStatus) AS 'Total'
FROM
userIndex u
LEFT JOIN pacesetterEntries pe ON u.userID = pe.studentID
WHERE classID = ? AND studentID = ?;`,
[user.userID, classID, classID, user.userID],
(err, results) => {
if (err) {
console.log(err);
} else {
results.forEach((child) => {
newArr.push({
studentID: child.studentID,
firstName: child.firstName,
lastName: child.lastName,
completed: child.Completed,
total: child.Total,
});
});
}
}
);
});
});
dataFetch;
}
}
);
};
The first query returns an array like this:
[ { userID: 244 }, { userID: 245 }, { userID: 250 } ]
For each of those userIDs, the second query is run. The result of that query looks like this:
[
{
studentID: 244,
firstName: 'Test',
lastName: 'Student1',
Completed: 0,
Total: 5
}
]
[
{
studentID: 245,
firstName: 'Test',
lastName: 'Student',
Completed: 1,
Total: 5
}
]
[
{
studentID: 250,
firstName: 'Cameron',
lastName: 'Erasmus',
Completed: 3,
Total: 5
}
]
What I am trying to achieve is getting an array similar to result #2 that I can send back to my frontend for mapping. Exactly like this:
[
{
studentID: 244,
firstName: "Test",
lastName: "Student1",
Completed: 0,
Total: 5,
},
{
studentID: 245,
firstName: "Test",
lastName: "Student",
Completed: 1,
Total: 5,
},
{
studentID: 250,
firstName: "Cameron",
lastName: "Erasmus",
Completed: 3,
Total: 5,
},
];
I've tried to push the result of query 2 into "newArr" but it always comes back empty. Where am I going wrong?

how to count records in prisma io?

I am executing a query but the result of the account adds the letter "n", I don't understand why when I execute the query in mysql console it shows it correctly.
const client = await prisma.$queryRaw`SELECT idClient, COUNT(*) as totalCount FROM sales GROUP BY idClient`;
console.log(client)
executing the same query but in heidiSQL.
Numbers with an n postfix denote the BigInt type in JavaScript MDN. This is probably due to some queryRaw changes that were made in v4.0.0. The Integer results are now being returned as BigInt. You must change your code to handle the new type. See this section of the upgrade guide.
Example: Given this Schema file
model Customers {
id Int #id #default(autoincrement())
customerName String
country String
}
and this script file
async function main() {
await prisma.customers.createMany({
data: [
{
country: 'USA',
customerName: 'John Doe',
},
{
country: 'Germany',
customerName: 'Jane Doe',
},
{
country: 'Canada',
customerName: 'Adams Doe',
},
],
});
const clients = await prisma.customers.groupBy({
by: ['country'],
_count: true,
});
console.log("Using normal client query with groupBy ")
console.log(clients);
const clientsWithRawQuery =
await prisma.$queryRaw`SELECT Country, COUNT(country) as totalCount
FROM Customers GROUP BY Country`;
console.log("\n Using queryRaw")
console.log(clientsWithRawQuery);
console.log(
'Before Conversion: Typeof Count:',
typeof clientsWithRawQuery[0].totalCount
);
clientsWithRawQuery.forEach((countryObject) => {
countryObject.totalCount = Number(countryObject.totalCount);
});
console.log(
'After Conversion: Typeof Count:',
typeof clientsWithRawQuery[0].totalCount
);
console.log('\n', clientsWithRawQuery)
}
The output is
Using normal client query with groupBy
[
{ _count: 2, country: 'Canada' },
{ _count: 2, country: 'Germany' },
{ _count: 2, country: 'USA' }
]
Using queryRaw
[
{ Country: 'Canada', totalCount: 2n },
{ Country: 'Germany', totalCount: 2n },
{ Country: 'USA', totalCount: 2n }
]
Before Conversion: Typeof Count: bigint
After Conversion: Typeof Count: number
[
{ Country: 'Canada', totalCount: 2 },
{ Country: 'Germany', totalCount: 2 },
{ Country: 'USA', totalCount: 2 }
]

How to return nested JSON in node js

I have three different tables.
1. Order details (id, itemId,date,userId)
2. Item details (id, itemName, quantity)
3. User details (id, userName)
I want to return a JSON as:
{[
{
orderId = 1,
items = [
{
itemId = 1,
itemName = ITEM_DEMO,
},
{
itemId = 2,
itemName = ITEM_DEMO2,
}
],
userDetails = {
userId = 1,
userName = TEST_USER
}
}
]}
How can we do this in Node JS. Im using MySQL.
First of all you should read about object and json in javascript.
For parsing your data from mySql to json do the following steps:
Create an object that is filled with your data from mySql.
const ArrayObjectFilledWithMysqlData = [
{
orderId: 1,
items: [{
itemId: 1,
itemName: ITEM_DEMO,
},
{
itemId: 2,
itemName: ITEM_DEMO2,
}]
},
{
userDetails: {
userId: 1,
userName: TEST_USER
}
}
]
Parse the Array to json.
const jsonFromData = JSON.stringify(ArrayObjectFilledWithMysqlData)