Prisma - Sum amount - more than 350’000 rows - sum

I have an Invoice model like:
type Invoice {
id
amount
}
I have 350'000 invoices. How can I sum amount for all invoices.
(Max limitation is 1000)
This hack cannot work: https://www.prisma.io/forum/t/query-all-size-limit/557, as I have too many rows.
Related issues: https://github.com/prisma/prisma/issues/2162 https://github.com/prisma/prisma/issues/259 https://www.prisma.io/forum/t/query-all-size-limit/557 https://www.prisma.io/forum/t/sun-amount-more-than-350000-rows/7611

You can build a custom resolver in Prisma with a custom SQL query that will SUM it for you;
An example implementation might be something like: :
const client = new Client({
database: "prisma",
user: "...",
password: "...",
host: "localhost",
port: 3000
})
const resolvers = {
Query: {
async sumInvoices(parent, args, context, info){
const response = await client.query(
`SELECT SUM(amount) FROM Invoice WHERE YOUR_CONDITION`
);
return response;
};
};
You can check out Ben Awad's video on it too for additional examples: https://www.youtube.com/watch?time_continue=12&v=YUjlBuI8xsU

Related

Strapi GROUP BY and COUNT fields with the same value

Is there any way in strapi to group by entries with the same fields and count its total?
Trying to create a Poll App which has "Response" Collection containing an "Answer" Field (enum: a, b, c, d). Would like to group responses with the same answers. Something like this:
{
"answer": "a",
"total": 3
}, {
"answer": "b",
"total": 1
}
Is it possible out of the box?
To give more context, here's its sql counterpart:
select *, count(answers) from responses group by answers
there is no known default way for groupby with entity service, however there is count query:
/src/answer/controllers/answer.js
const { createCoreController } = require("#strapi/strapi").factories;
module.exports = createCoreController("api::answer.answer", ({ strapi }) => ({
async find(ctx) {
let { query } = ctx;
let answers = await strapi.db.query("api::answer.answer").findMany({
...query,
});
answers = await Promise.all(answers.map(async (answer) => ({
...answer,
total: await strapi.db.query("api::answer.answer").count({where: '...'})
})))
return answers
},
}));
or you can use raw query like this:
let { rows } = await strapi.db.connection.raw(
`select id from posts where published_at IS NOT null order by random() limit ${count};
`);
or
let { rows } = await strapi.db.connection.raw(
`select *, count(answers) from responses group by answers;`);

Infinite loop with a graphql and mongoose backend

I have a backend made in express and mongoose:
all my mutations and queries work perfectly except one mutation sends me an infinite loader
updateVehicleVerification: async (_, { id, updateVehicleVerification }) => {
const vehicleVeri = await VehicleVerification.findById(id);
if (!vehicleVeri) {
throw new Error(ErrorMessage + ' : Verification de Vehicule');
}
await VehicleVerification.findByIdAndUpdate(
id,
updateVehicleVerification
);
const veri = await VehicleVerification.findById(id);
return veri;
},
and the query I use here:
export const UPDATE_CONTROL_VEHICLE = gqlmutation updateVehicleVerification( $id: String! $updateVehicleVerification: VerificationVehicleInput ) { updateVehicleVerification( id: $id updateVehicleVerification: $updateVehicleVerification ) { honk { state image comment } mileage dateVerification stateVehicle { damaged good missing } } };
enter code here
I I solved the problem !
I did not manage the case where the data reached me by the request which keyed an infinite loop.

How to show generated SQL / raw SQL in TypeORM queryBuilder

I developed typeorm querybuilder. For the purpose of debugging, I'd like to show the generated SQL query.
I tested printSql() method, but it didn't show any SQL query.
const Result = await this.attendanceRepository
.createQueryBuilder("attendance")
.innerJoin("attendance.child", "child")
.select(["attendance.childId","child.class","CONCAT(child.firstName, child.lastName)"])
.where("attendance.id= :id", { id: id })
.printSql()
.getOne()
console.log(Result);
It returned the following:
Attendance { childId: 4, child: Child { class: 'S' } }
My desired result is to get the generated SQL query.
Is there any wrong point? Is there any good way to get the SQL query?
.getQuery() or .getSql()
const sql1 = await this.attendanceRepository
.createQueryBuilder("attendance")
.innerJoin("attendance.child", "child")
.select(["attendance.childId","child.class","CONCAT(child.firstName, child.lastName)"])
.where("attendance.id= :id", { id: id })
.getQuery();
console.log(sql1);
const sql2 = await this.attendanceRepository
.createQueryBuilder("attendance")
.innerJoin("attendance.child", "child")
.select(["attendance.childId","child.class","CONCAT(child.firstName, child.lastName)"])
.where("attendance.id= :id", { id: id })
.getSql();
console.log(sql2);
printSql can also be used, but it will only print when logging is enabled.
#Module({
imports: [
TypeOrmModule.forRoot({
...options
logging: true
}),
],
})
await this.attendanceRepository
.createQueryBuilder("attendance")
.innerJoin("attendance.child", "child")
.select(["attendance.childId","child.class","CONCAT(child.firstName, child.lastName)"])
.where("attendance.id= :id", { id: id })
.printSql();

Is smart query custom variable name possible?

I'm using Vue alongside with Apollo in order to query a GraphQL endpoint in my project. Everything's fine but I want to start programming generic components to ease and fasten the development.
The thing is, in most views, I use the Smart Query system.
For instance, I use :
apollo: {
group: {
query: GROUP_QUERY,
variables () { return { id: this.groupId } },
skip () { return this.groupId === undefined },
result ({ data }) {
this.form.name = data.group.name
}
}
}
With the GROUP_QUERY that is :
const GROUP_QUERY = gql`
query groupQuery ($id: ID) {
group (id: $id) {
id
name
usersCount
userIds {
id
username
}
}
}
`
So my group variable in my apollo smart query has the same name as the query itself group (id: $id). It is this mechanism that is quite annoying for what I try to achieve. Is there a way to avoid that default mechanism ?
I'd like for instance to be able to give a generic name such as record, and it would be records for queries that potentially return multiple records.
With that, I would be able to make generic components or mixins that operate either on record or records.
Or have I to rename all my queries to record and records which would be annoying later on in case of troubleshooting with error messages ?
Or maybe there's another way to achieve that and I didn't think about it ?
Thanks in advance.
You can, in fact, rename the variable of Apollo smart queries using the update option, as seen here in the Vue Apollo documentation. Your example would look like:
apollo: {
record: {
query: GROUP_QUERY,
variables () { return { id: this.groupId } },
update: (data) => data.group,
skip () { return this.groupId === undefined },
result ({ data }) {
this.form.name = data.group.name
}
}
}
You should notice that the Apollo object will create a record variable in your component, and the update statement shows where to get the group for the record.
By doing so :
const GROUP_QUERY = gql`
query groupQuery ($id: ID) {
record: group (id: $id) {
id
name
usersCount
userIds {
id
username
}
}
}
`
If the GROUP_QUERY is used at several places, the result will be accessible under the record name, because it is defined as an alias over group.
See documentation for Aliases.

Express js + Sequelize and hook

I am developping an application where I need to make extra validation on creating an object.
I tried using hooks and the beforeValidate function, but it's not working. I'm trying to fail the validation if the value submitted is greater than the value from the db (computed value based on custom query).
Transaction.beforeValidate(function(transaction, options) {
sequelize.query(
'SELECT SUM(IF(type = "buy", number_of_shares, number_of_shares * -1)) as remaining FROM transactions WHERE account_id = $account_id',
{
bind: {
account_id: req.body.account_id
},
type: sequelize.QueryTypes.SELECT
}
).then(result => {
if (req.body.type == "sell" && result.remaining < req.body.number_of_shares) {
throw error('Number of remaining shares is less than what you are trying to sell.') // psudeo code
}
}).then(result => {
return sequelize.Promise.resolve(user);
})
})
You're missing a return before sequelize.query(.
return sequelize.query(