How to use Query with relations ?

Hello, I'm encountering an issue when trying to execute a query with relations in my code. Here's the function I'm working with:
async getOneWithRelations(id: string): Promise<AlbumWithRelationsResponse> {
const { db, withErrorHandling } = this;
return withErrorHandling(async () => {
const { uuid } = uuidSchema.parse({ uuid: id });
const result = await db.query.albumTable.findFirst({
where: eq(albumTable.id, uuid),
with: {
images: true,
},
});
console.log(result);
return result;
});
}
async getOneWithRelations(id: string): Promise<AlbumWithRelationsResponse> {
const { db, withErrorHandling } = this;
return withErrorHandling(async () => {
const { uuid } = uuidSchema.parse({ uuid: id });
const result = await db.query.albumTable.findFirst({
where: eq(albumTable.id, uuid),
with: {
images: true,
},
});
console.log(result);
return result;
});
}
When I run this function, I receive the following error:
TypeError: Cannot read properties of undefined (reading 'referencedTable')
TypeError: Cannot read properties of undefined (reading 'referencedTable')
I suspect there might be an issue with my schema. Could you help me identify and resolve the problem?
6 Replies
maupiszon
maupiszonOP15mo ago
import { boolean, pgTable, smallint, uuid, varchar } from "drizzle-orm/pg-core";
import { relations } from "drizzle-orm";
import { randomUUID } from "node:crypto";

export const categoryTable = pgTable("Category", {
id: varchar("id", { length: 36 })
.primaryKey()
.$defaultFn(() => randomUUID()),
name: varchar("name", { length: 255 }).notNull().unique(),
order: smallint("order").default(0).notNull(),
show: boolean("show").default(false).notNull(),
});

export const albumTable = pgTable("Album", {
id: varchar("id", { length: 36 })
.primaryKey()
.$defaultFn(() => randomUUID()),
title: varchar("title", { length: 255 }).notNull().default(""),
subtitle: varchar("subtitle", { length: 255 }),
show: boolean("show").default(false).notNull(),
categoryId: varchar("categoryId", { length: 36 }).references(
() => categoryTable.id,
{
onDelete: "set null",
},
),
coverId: varchar("coverId", { length: 36 }),
});

export const imageTable = pgTable("Image", {
id: varchar("id", { length: 36 })
.primaryKey()
.$defaultFn(() => randomUUID()),
albumId: varchar("albumId", { length: 36 }).references(() => albumTable.id, {
onDelete: "cascade",
}),
path: varchar("patch", { length: 255 }).notNull(),
});

const categoryRelation = relations(categoryTable, ({ many }) => ({
albums: many(albumTable),
}));

const imageRelation = relations(imageTable, ({ one }) => ({
album: one(albumTable, {
fields: [imageTable.albumId],
references: [albumTable.id],
}),
}));

const albumRelation = relations(albumTable, ({ one, many }) => ({
category: one(categoryTable, {
fields: [albumTable.categoryId],
references: [categoryTable.id],
}),
images: many(imageTable),
}));
import { boolean, pgTable, smallint, uuid, varchar } from "drizzle-orm/pg-core";
import { relations } from "drizzle-orm";
import { randomUUID } from "node:crypto";

export const categoryTable = pgTable("Category", {
id: varchar("id", { length: 36 })
.primaryKey()
.$defaultFn(() => randomUUID()),
name: varchar("name", { length: 255 }).notNull().unique(),
order: smallint("order").default(0).notNull(),
show: boolean("show").default(false).notNull(),
});

export const albumTable = pgTable("Album", {
id: varchar("id", { length: 36 })
.primaryKey()
.$defaultFn(() => randomUUID()),
title: varchar("title", { length: 255 }).notNull().default(""),
subtitle: varchar("subtitle", { length: 255 }),
show: boolean("show").default(false).notNull(),
categoryId: varchar("categoryId", { length: 36 }).references(
() => categoryTable.id,
{
onDelete: "set null",
},
),
coverId: varchar("coverId", { length: 36 }),
});

export const imageTable = pgTable("Image", {
id: varchar("id", { length: 36 })
.primaryKey()
.$defaultFn(() => randomUUID()),
albumId: varchar("albumId", { length: 36 }).references(() => albumTable.id, {
onDelete: "cascade",
}),
path: varchar("patch", { length: 255 }).notNull(),
});

const categoryRelation = relations(categoryTable, ({ many }) => ({
albums: many(albumTable),
}));

const imageRelation = relations(imageTable, ({ one }) => ({
album: one(albumTable, {
fields: [imageTable.albumId],
references: [albumTable.id],
}),
}));

const albumRelation = relations(albumTable, ({ one, many }) => ({
category: one(categoryTable, {
fields: [albumTable.categoryId],
references: [categoryTable.id],
}),
images: many(imageTable),
}));
maupiszon
maupiszonOP15mo ago
No description
Angelelz
Angelelz15mo ago
How are you creating the db object? You need to pass it the schema with the tables and relations defined.
maupiszon
maupiszonOP15mo ago
No description
maupiszon
maupiszonOP15mo ago
# index.ts
export * from "./enums";
export * from "./album";
export * from "./week-intentions";
export * from "./admin";
export * from "./announcement";
# index.ts
export * from "./enums";
export * from "./album";
export * from "./week-intentions";
export * from "./admin";
export * from "./announcement";
# client.ts
import * as schema from "./schema";
import { drizzle } from "drizzle-orm/node-postgres";
import { Client } from "pg";
import { env } from "../config/env/server";

const { DATABASE_URL } = env;

export const client = new Client({
connectionString: DATABASE_URL,
});

(async () => {
try {
await client.connect();
} catch (error) {
console.log(error);
await client.end();
}
})();

export const db = drizzle(client, { schema });
# client.ts
import * as schema from "./schema";
import { drizzle } from "drizzle-orm/node-postgres";
import { Client } from "pg";
import { env } from "../config/env/server";

const { DATABASE_URL } = env;

export const client = new Client({
connectionString: DATABASE_URL,
});

(async () => {
try {
await client.connect();
} catch (error) {
console.log(error);
await client.end();
}
})();

export const db = drizzle(client, { schema });
and i have base crud class
export class DefaultCrud<T extends PgTable> {
// import from client.ts
protected db = db;
protected insertSchema: ReturnType<typeof createInsertSchema>;

constructor(protected model: T) {
this.insertSchema = createInsertSchema(this.model);
}

protected async withErrorHandling<R, D = null>(
fn: () => Promise<R>,
defaultValue: D = null as unknown as D,
): Promise<R | D> {
try {
return await fn();
} catch (error) {
console.error(error);
return defaultValue;
}
}

async create(data: InferInsertModel<T>): Promise<T["$inferSelect"] | null> {
const { withErrorHandling, db, model, insertSchema } = this;
return withErrorHandling(async () => {
const parsedData = insertSchema.parse(data);
const [result] = (await db
.insert(model)
.values(parsedData)
.returning()) as unknown[];
return result as T["$inferSelect"];
});
}
--- rest
export class DefaultCrud<T extends PgTable> {
// import from client.ts
protected db = db;
protected insertSchema: ReturnType<typeof createInsertSchema>;

constructor(protected model: T) {
this.insertSchema = createInsertSchema(this.model);
}

protected async withErrorHandling<R, D = null>(
fn: () => Promise<R>,
defaultValue: D = null as unknown as D,
): Promise<R | D> {
try {
return await fn();
} catch (error) {
console.error(error);
return defaultValue;
}
}

async create(data: InferInsertModel<T>): Promise<T["$inferSelect"] | null> {
const { withErrorHandling, db, model, insertSchema } = this;
return withErrorHandling(async () => {
const parsedData = insertSchema.parse(data);
const [result] = (await db
.insert(model)
.values(parsedData)
.returning()) as unknown[];
return result as T["$inferSelect"];
});
}
--- rest
and handler
class Album extends DefaultCrud<typeof albumTable> {
constructor() {
super(albumTable);
}

async getOneWithRelations(id: string): Promise<AlbumWithRelationsResponse> {
const { db, withErrorHandling } = this;
return withErrorHandling(async () => {
const { uuid } = uuidSchema.parse({ uuid: id });
const result = await db.query.albumTable.findFirst({
where: eq(albumTable.id, uuid),
with: {
images: true,
},
});
console.log(result);
return result;
});
}
}
class Album extends DefaultCrud<typeof albumTable> {
constructor() {
super(albumTable);
}

async getOneWithRelations(id: string): Promise<AlbumWithRelationsResponse> {
const { db, withErrorHandling } = this;
return withErrorHandling(async () => {
const { uuid } = uuidSchema.parse({ uuid: id });
const result = await db.query.albumTable.findFirst({
where: eq(albumTable.id, uuid),
with: {
images: true,
},
});
console.log(result);
return result;
});
}
}
OK i get it i have to export the relations @angelelz thanks men
Angelelz
Angelelz15mo ago
Lol, I didn't do anything
Want results from more Discord servers?
Add your server