trying to group by artist using Sequelize and NodeJs - mysql

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,
});
},
},
},
});`

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

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 }
]

SQL - Nested result instead of merge when left join

I have a SQL LEFT JOIN like this:
var getEmail = req.body.email;
const connection = require('../conig/db');
let promise = await new Promise((resolve,reject)=>{
connection.query("SELECT users.id, users.account_id, users.email, accounts.id, accounts.company FROM users LEFT JOIN accounts ON accounts.id=users.account_id WHERE users.email = ?",[getEmail], function(err, rows) {
if (err) {
console.log(err);
resolve();
}
console.log('rows:');
console.log(rows);
resolve();
});
});
The result merges the columns:
[{
id: 1,
account_id: '1',
email: 'user01#domain',
company: 'Company 01'
}, {
id: 3,
account_id: '3',
email: 'user02#domain',
company: 'Company 02'
}, {
id: null,
account_id: '',
email: 'user03#domain',
company: null
}]
But what I would like to have is a nested result with the table name at first level like this:
[{
users: {
account_id: '1',
email: "user01#domain",
id: 1
},
accounts: {
company: "Company 01",
id: 1
}
}, {
users: {
account_id: '3',
email: "user02#domain",
id: 2
},
accounts: {
company: "Company 03",
id: 3
}
}, {
users: {
account_id: '',
email: "user03#domain",
id: 3
},
accounts: {
company: null,
id: null
}
}]
How can I achieve this?
I tried:
SELECT users.id AS users.id, users.account_id AS users.account_id, users.email AS users.email, accounts.id AS accounts.id, accounts.company AS accounts.company FROM users LEFT JOIN accounts ON accounts.id=users.account_id
-> Error

Create a dynamic Mysql Insert from an Object

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.

Angular7/Display list of fieldsets from array grouped by specific field

typescript has an array like :
'let list = [ { name: 'sdd', ident: 'Fe', groupId: 3 }, { name: 'sss', ident: 'Cu', groupId : 0 }, { name: '1050 AJ', ident: 'Mn', groupId: 3 }, { name: 'X332.0 AC', ident: 'V', groupId: 3 }, { name: 'X4002', ident: 'Mm', groupId : 0 }, { name: 'X400s', ident: 'cn', groupId : 4 }, { name: 'X4002 z', ident: 'xx', groupId : 4 }, ];'
Using Angular & html : I wanna group them with groupId field and display in fieldset with the first name of list and if groupId == 0 it should have it's own fieldset like :
sdd:
ident: 'Fe'
ident: 'Mn'
ident: 'V'
==============
sss:
ident: 'Cu'
==============
X4002:
ident: 'Mm
==============
X400s:
ident: 'cn'
ident: 'xx'
==============
You can make a new object to do what you are trying to achieve and then can display this using loops in your Angular as you desire.
let list = [ { name: 'sdd', ident: 'Fe', groupId: 3 },
{ name: 'sss', ident: 'Cu', groupId : 0 },
{ name: '1050 AJ', ident: 'Mn', groupId: 3 },
{ name: 'X332.0 AC', ident: 'V', groupId: 3 },
{ name: 'X4002', ident: 'Mm', groupId : 0 },
{ name: 'X400s', ident: 'cn', groupId : 4 },
{ name: 'X4002 z', ident: 'xx', groupId : 4 }, ];
const formattedlist = {};
formattedlist[0] = [];
for(let i=0;i<list.length;i++){
let obj = {};
if(list[i].groupId===0){
obj[list[i].name] = {ident: list[i].ident};
formattedlist[0].push(obj);
}
else{
if(formattedlist[list[i].groupId] === undefined){
formattedlist[list[i].groupId] = {};
formattedlist[list[i].groupId].name = list[i].name;
formattedlist[list[i].groupId].ident = [list[i].ident];
}
else{
formattedlist[list[i].groupId]['ident'].push(list[i].ident);
}
}
}
console.log(formattedlist);