How to add where clause for one to one relations in drizzle query?

I have these two schemas: export const users = mysqlTable("User", { id: text("id").primaryKey(), name: text("name"), email: text("email"), emailVerified: datetime("emailVerified", { mode: "date", fsp: 3 }), image: text("image"), role: text("role").default("artist").notNull(),, }); export const payments = mysqlTable("Payment", { userId: text("userId").notNull(), customerId: text("customerId").notNull(), subscriptionId: text("subscriptionId"), planName: text("planName").notNull(), subscriptionStatus: stripeSubscriptionStatusEnum("subscriptionStatus"), subscriptionCreated: datetime("subscriptionCreated", { mode: "date", fsp: 3, }), }); With relation: export const paymentsRelations = relations(payments, (helpers) => ({ user: helpers.one(users, { relationName: "PaymentToUser", fields: [payments.userId], references: [users.id], }), })); export const usersRelations = relations(users, (helpers) => ({ Payment: helpers.one(payments, { relationName: "PaymentToUser", fields: [users.id], references: [payments.userId], }), })); I want to retrieve all the users with planName 'Plan A', but having difficulties in forming a drizzle relational query for this. The one I am using is: db.users.query.findMany({ with: { Payment: true }, where: eq(Payment.planName, 'Plan A') }) This is giving me 'Unknown column Payment.planName' error and rightly so because in resulting SQL, there is no reference to Payment table on its own. My question is how can I achieve this using queries? I know I can use drizzle query builders with joins for this but I want to do it in relations query as query builders does not give me output in desired format. In other words, how can I filter parent table based on a condition given to a related table which are related with one-to-one relation?
5 Replies
Se7enVision
Se7enVisionOP9mo ago
One solution I found is adding this in WHERE clause : sqlid IN (SELECT userId from Payment WHERE planName=${plan}). But I would appreciate a cleaner solution
Aaroned
Aaroned9mo ago
@Se7enVision try querying from the payment instead db.payments.query.findMany({ with: { user: true }, where: eq(Payment.planName, 'Plan A') })
Se7enVision
Se7enVisionOP9mo ago
Hey @Aaroned Thanks for the response. This would work fine but I have several other relations which I am using with users table to get my data. I only shared the Payment one to shorten the question. I have a datatable in which I have to render users along with user related info present in other tables, so I can only do db.users.query in order to accomodate for them. This is how my complete query looks like: const users = await ctx.db.query.users.findMany({ with: { albums: { columns: {}, with: { tracks: true, MusicVideo: true, } }, ......bunch of relations Payment: { columns: { planName: true } } }, where: !operator || operator === "and" ? and( ...where, filters?.planName ? eq(payment.planName, filters.planName) : undefined, ) : or( ...where, filters?.planName ? eq(payment.planName, filters.planName) : undefined ), limit: input.limit ?? 10, offset: input.offset ?? 0, }) The line filters?.planName ? eq(payment.planName, filters.planName) : undefined obviously does not work and gives the error 'user.planName is unknown' which it is in this context. So I have to use above method for it.
Aaroned
Aaroned9mo ago
@Se7enVision if that’s the case, you will need to use the exists clause with a subquery. Something like
.where(exists(db.select({result: sql`1`}).from(payments).where(and(eq(payments.planName,’Plan A’),eq(payments.userId,users.id)))))
.where(exists(db.select({result: sql`1`}).from(payments).where(and(eq(payments.planName,’Plan A’),eq(payments.userId,users.id)))))
Se7enVision
Se7enVisionOP9mo ago
@Aaroned Thanks I'll look into it.
Want results from more Discord servers?
Add your server