Related
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,
});
},
},
},
});`
I want to fire a query to get such a result:
[{
id: 1,
brandName: "x"
brandModels: [
{id: 1, modelName: "abc", createdAt: "yyyy-mm-dd"},
{id: 2, modelName: "def", createdAt: "yyyy-mm-dd"},
]
},
{
id: 2,
brandName: "y"
brandModels: [
{id: 4, modelName: "ghi", createdAt: "yyyy-mm-dd"},
{id: 5, modelName: "jkl", createdAt: "yyyy-mm-dd"},
]
}]
Tables Schema
BrandsTable
{id, brandName, brand_id}
ModelsTable
{id, modelName, createdAt}
I guess it's not possible like that? I don't have any experience with text-based databases, but I can well imagine that this can be achieved with a MongoDB. Because ultimately I want to have a js object at the end of the day.
Here's an example but I have not tested it:
SELECT JSON_ARRAYAGG(
JSON_OBJECT(
'id', b.id,
'brandName', b.brandName,
'brandModels', m.modelArray
)
) AS joined_result
FROM BrandTable AS b
JOIN (
SELECT brand_id, JSON_ARRAYAGG(
JSON_OBJECT(
'id', id,
'modelName', modelName,
'createdAt', createdAt
)
) AS modelArray
FROM ModelsTable
GROUP BY brand_id
) AS m USING (brand_id);
Note that I had to assume the ModelsTable also contains a column for brand_id, otherwise there is nothing to use in the join condition.
Read documentation for JSON_OBJECT() and JSON_ARRAYAGG() for more information about how these functions work.
I have three different tables:
users
posts
comments
And I would like to get a result like this:
posts: [
{
id: 1,
text: "Looking for something else specific here",
author: {
id: 3,
image: "https://lh3.googleusercontent.com",
username: "AR"
},
comments: [
{
id: 1,
text: 'Try this!',
author: {
id: 4,
image: "https://lh3.googleusercontent.com",
username: "AM"
}
},
{
id: 2,
text: 'Thanks!',
author: {
id: 3,
image: "https://lh3.googleusercontent.com",
username: "AR"
}
},
],
created_at: "2021-08-18 01:16:58.000000",
updated_at: "2021-08-18 01:16:58.000000"
},
{
id: 2,
text: "Looking for something specific here",
author: {
id: 4,
image: "https://lh3.googleusercontent.com",
username: "AM"
},
comments: [
null
],
created_at: "2021-08-18 01:18:13.000000",
updated_at: "2021-08-18 01:18:13.000000"
}
]
So far I have this:
SELECT
cast(concat('[', group_concat(
JSON_OBJECT(
'id', p.id,
'text', p.text,
'author', JSON_OBJECT(
'id', u.id,
'username', u.ofdb_username,
'image', u.image
),
'comments', JSON_OBJECT(
'id', c.id,
'text', c.text,
'created_at', c.created_at,
'updated_at', c.updated_at
),
'created_at', p.created_at,
'updated_at', p.updated_at
) SEPARATOR ','), ']') as json) as posts
FROM posts as p
LEFT JOIN users as u
ON p.users_id = u.id
LEFT JOIN comments as c
on c.posts_id = p.id
However if there is more than one comment, the same post is repeated twice because of the LEFT JOIN. I also haven't tried to join users a second time to get the comment's author data.
Since I was using Next.js, I ended up switching to Prisma's ORM model which made this so much easier.
I know this isn't a direct answer but to all futurecomers: try to forgo writing SQL code and use an ORM like Prisma.
I have a simple relation company has many projects and everything is super fine, when I get the result parent ID is missing from entity object while its present in query
Company Entity :
#Entity()
export class Company {
#PrimaryGeneratedColumn({ unsigned: true })
id: number;
#Column({ nullable: false })
name: string;
#Column({
type: 'datetime',
nullable: false,
default: () => 'CURRENT_TIMESTAMP',
})
created_at;
#Column({ nullable: true, type: 'datetime' })
updated_at;
#OneToMany(
type => Project,
project => project.company
)
project: Project[];
}
Project Entity :
#Entity()
export class Project {
#PrimaryGeneratedColumn({ unsigned: true })
id: number;
#Column({ nullable: false })
name: string;
#ManyToOne(
type => Company,
company => company.project,
{ nullable: false }
)
#JoinColumn({ name: 'company_id' })
company: Company;
#Column({
type: 'datetime',
nullable: false,
default: () => 'CURRENT_TIMESTAMP',
})
created_at;
#Column({ nullable: true, type: 'datetime' })
updated_at;
}
Query in service :
return this.companyRepository.find({ where: { id: 1 }, relations: ['project'] })
Query log is :
SELECT
`Company`.`id` AS `Company_id`,
`Company`.`name` AS `Company_name`,
`Company`.`created_at` AS `Company_created_at`,
`Company`.`updated_at` AS `Company_updated_at`,
`Company__project`.`id` AS `Company__project_id`,
`Company__project`.`name` AS `Company__project_name`,
`Company__project`.`created_at` AS `Company__project_created_at`,
`Company__project`.`updated_at` AS `Company__project_updated_at`,
`Company__project`.`company_id` AS `Company__project_company_id`
FROM
`company` `Company`
LEFT JOIN
`project` `Company__project` ON `Company__project`.`company_id` = `Company`.`id`
WHERE
`Company`.`id` = 1;
but when i print result my company object contains project array but in project array company_id is missing or typeorm has excluded it while creating an object, is there any way than i can get parent_id which is company_id in project object
Result :
Company {
id: 1,
name: 'company',
created_at: 2020-10-24T18:46:59.000Z,
updated_at: null,
project: [
Project {
id: 1,
name: 'project 1',
created_at: 2020-10-24T18:47:35.000Z,
updated_at: null
},
Project {
id: 2,
name: 'project 2',
created_at: 2020-10-24T19:08:08.000Z,
updated_at: null
}
]
}
expected result :
Company {
id: 1,
name: 'company',
created_at: 2020-10-24T18:46:59.000Z,
updated_at: null,
project: [
Project {
id: 1,
company_id: 1, <========= this is required
name: 'project 1',
created_at: 2020-10-24T18:47:35.000Z,
updated_at: null
},
Project {
id: 2,
company_id: 1,
name: 'project 1',
created_at: 2020-10-24T19:08:08.000Z,
updated_at: null
}
]
}
In the fireld 'company_id' you are not supposed to get the id field of company, as it is the company object itself. So from that object you may get its id. I think that if you would set 'eager: true' on the field, you will get the object in the query, because the default is eager: false.
If what you want is only the id and not the whole object, maube think of a field which is a foreign key to the company id using one-to-one relation, which will give you your wanted reault output
I think you should be able to split that up like this. companyId will automatically be extracted from company.
// ...
#ManyToOne(type => Company, company => company.project)
company: Company;
#Column({nullable: true})
companyId: number;
// ...
Suppose I have a table like this:
and an array of objects which contains [
{ID: '0', Name: 'Leo', Age: 21, CurrentState: 5},
{ID: '1', Name: 'George', Age: 26, , CurrentState: 6},
{ID: '2', Name: 'Diana', Age: 27, , CurrentState: 4}
].
How can I update the columns ID, Name, Age, and CurrentState without affecting the values of IsAdmin column?
If I run the following code
Table.bulkCreate([
{ID: '0', Name: 'Leo', Age: 21, CurrentState: 5},
{ID: '1', Name: 'George', Age: 26, , CurrentState: 6},
{ID: '2', Name: 'Diana', Age: 27, , CurrentState: 4}
], {
updateOnDuplicate: true
})
All the values of IsAdmin of the updated rows will be set to FALSE, which is its default value.
How can I avoid this problem?
Just passe an array of only the attributes that need to be updated
Table.bulkCreate([
{ID: '0', Name: 'Leo', Age: 21, CurrentState: 5},
{ID: '1', Name: 'George', Age: 26, , CurrentState: 6},
{ID: '2', Name: 'Diana', Age: 27, , CurrentState: 4}
], {
updateOnDuplicate: ['Name','CurrentState']
})
options.updateOnDuplicate
Array
optional
Fields to update if row key already exists (on duplicate key update)? (only supported by mysql). By default, all fields are updated.