Dynamic Drizzle Relational Queries

Hi everybody, hope all is well. I was wondering if there is a way to build dynamic queries when using drizzle (relational) queries. I read the section on dynamic query building but it doesn't cover relational queries. I'm building a rest API and I want users to be able to pass filters via query params. I have a tours table, tours can have many images as well as many start dates. Is there a way of doing something like this? And make it flexible enough so that the user can filter based on various operations for different columns (ie: equal, lt, lte, gt, gte, like, etc...).
// pseudo code

db.query.tours.findMany({
where: <dynamically generated where filters for tour>,
with: { images: {
where: <dynamically generated where filters for images>
}, startDates: {
where: <dynamically generated where filters for start dates>
} },
})
// pseudo code

db.query.tours.findMany({
where: <dynamically generated where filters for tour>,
with: { images: {
where: <dynamically generated where filters for images>
}, startDates: {
where: <dynamically generated where filters for start dates>
} },
})
How would you solve this? Thanks in advance, this would help me a lot.
5 Replies
ericmartinezr
ericmartinezr14mo ago
I have something similar in my code, it may be useful
const table1Conditions: SQLWrapper[] = [];
const table2Conditions: SQLWrapper[] = [];

if (frontendFilter1) {
table1Conditions.push( inArray(table1.field, [1,2,3]) );
}

if (frontendFilter2) {
table2Conditions.push( eq(table2.field, frontendFilter2) );
}

db.query.table1.findMany({
where: and(...table1Conditions),
with {
table2: {
where: and(...table2Conditions)
}
}
});
const table1Conditions: SQLWrapper[] = [];
const table2Conditions: SQLWrapper[] = [];

if (frontendFilter1) {
table1Conditions.push( inArray(table1.field, [1,2,3]) );
}

if (frontendFilter2) {
table2Conditions.push( eq(table2.field, frontendFilter2) );
}

db.query.table1.findMany({
where: and(...table1Conditions),
with {
table2: {
where: and(...table2Conditions)
}
}
});
If the arrays are empty the where condition won't even show up so it's not a problem. Hopefully it makes sense.
Angelelz
Angelelz14mo ago
The problem with this approach is that the types will be wrong You need to wrap your findMany call in a generic fuction for it to properly infer the types dynamically I'll put together an example as this seems to be an issue people run into frequently and don't know how to figure it out
Angelelz
Angelelz14mo ago
GitHub
Relations input · drizzle-team drizzle-orm · Discussion #1483
I have a schema that looks like somewhat like this: export const employeesSchema = pgTable('employees', { firstName: varchar('first_name', { length: 256 }), lastName: varchar('l...
eduardoaosorio
eduardoaosorioOP14mo ago
@Angelelz I created this buildAndConditions function to generate the where, but typed it as any would you happen to know how I could type this properly?
const testQueryObject = {
price: { gte: 2000 },
difficulty: 'medium',
};


// how would you type this without using any?

const buildAndConditions = ({ table, operations, queryObject }: any) => {
const conditions = [];

for (const key in queryObject) {
const filter = queryObject[key];

if (filter instanceof Object) {
Object.entries(filter).forEach(([operator, value]) => {
conditions.push(operations[operator](table[key], value));
});
} else {
conditions.push(operations.eq(table[key], filter));
}
}

return operations.and(...conditions);
};

const query = db.query.tours.findMany({
where: (tours, operations) => {
const conditions = buildAndConditions({
table: tours,
operations,
queryObject: testQueryObject,
});

return conditions;
},
with: {
images: true,
startDates: true,
},
});
const testQueryObject = {
price: { gte: 2000 },
difficulty: 'medium',
};


// how would you type this without using any?

const buildAndConditions = ({ table, operations, queryObject }: any) => {
const conditions = [];

for (const key in queryObject) {
const filter = queryObject[key];

if (filter instanceof Object) {
Object.entries(filter).forEach(([operator, value]) => {
conditions.push(operations[operator](table[key], value));
});
} else {
conditions.push(operations.eq(table[key], filter));
}
}

return operations.and(...conditions);
};

const query = db.query.tours.findMany({
where: (tours, operations) => {
const conditions = buildAndConditions({
table: tours,
operations,
queryObject: testQueryObject,
});

return conditions;
},
with: {
images: true,
startDates: true,
},
});
Want results from more Discord servers?
Add your server