Dynamic query builder in convex
I'm trying to do a dynamic query based on conditions
schema.ts
I get a huge error, sorry for the spam
and all the args need to be marked with
import { v } from "convex/values";
import { BookingStatus } from "./lib/bookings";
import { query } from "./_generated/server";
export const getBookings = query({
args: {
studentId: v.optional(v.id("users")),
tutorId: v.optional(v.id("users")),
status: v.optional(
v.union(
v.literal(BookingStatus.AWAITING_TUTOR_CONFIRMATION),
v.literal(BookingStatus.AWAITING_STUDENT_CONFIRMATION),
v.literal(BookingStatus.AWAITING_PAYMENT),
v.literal(BookingStatus.PAYMENT_FAILED),
v.literal(BookingStatus.SCHEDULED),
v.literal(BookingStatus.CANCELED),
v.literal(BookingStatus.COMPLETED)
)
),
startDate: v.optional(v.number()), // Unix timestamp in milliseconds
endDate: v.optional(v.number()), // Unix timestamp in milliseconds
},
handler: async (ctx, args) => {
let query = ctx.db.query("bookings");
if (args.studentId) {
query = query.withIndex("by_student", (q) =>
q.eq("student", args.studentId!)
);
}
if (args.tutorId) {
query = query.withIndex("by_tutor", (q) => q.eq("tutor", args.tutorId));
}
if (args.status) {
query = query.withIndex("by_status", (q) => q.eq("status", args.status));
}
if (args.startDate !== undefined) {
query = query.filter((q) => q.gte(q.field("startTime"), args.startDate));
}
if (args.endDate !== undefined) {
query = query.filter((q) => q.lte(q.field("startTime"), args.endDate));
}
return await query.collect();
},
});import { v } from "convex/values";
import { BookingStatus } from "./lib/bookings";
import { query } from "./_generated/server";
export const getBookings = query({
args: {
studentId: v.optional(v.id("users")),
tutorId: v.optional(v.id("users")),
status: v.optional(
v.union(
v.literal(BookingStatus.AWAITING_TUTOR_CONFIRMATION),
v.literal(BookingStatus.AWAITING_STUDENT_CONFIRMATION),
v.literal(BookingStatus.AWAITING_PAYMENT),
v.literal(BookingStatus.PAYMENT_FAILED),
v.literal(BookingStatus.SCHEDULED),
v.literal(BookingStatus.CANCELED),
v.literal(BookingStatus.COMPLETED)
)
),
startDate: v.optional(v.number()), // Unix timestamp in milliseconds
endDate: v.optional(v.number()), // Unix timestamp in milliseconds
},
handler: async (ctx, args) => {
let query = ctx.db.query("bookings");
if (args.studentId) {
query = query.withIndex("by_student", (q) =>
q.eq("student", args.studentId!)
);
}
if (args.tutorId) {
query = query.withIndex("by_tutor", (q) => q.eq("tutor", args.tutorId));
}
if (args.status) {
query = query.withIndex("by_status", (q) => q.eq("status", args.status));
}
if (args.startDate !== undefined) {
query = query.filter((q) => q.gte(q.field("startTime"), args.startDate));
}
if (args.endDate !== undefined) {
query = query.filter((q) => q.lte(q.field("startTime"), args.endDate));
}
return await query.collect();
},
});schema.ts
bookings: defineTable({
student: v.id("users"), // Reference to the student (user with role STUDENT)
tutor: v.id("users"), // Reference to the tutor (user with role TUTOR)
service: v.id("services"), // Reference to the service being booked
type: v.union(
v.literal(BookingType.FREE_MEETING),
v.literal(BookingType.LESSON)
), // Booking type
status: v.union(
v.literal(BookingStatus.AWAITING_TUTOR_CONFIRMATION),
v.literal(BookingStatus.AWAITING_STUDENT_CONFIRMATION),
v.literal(BookingStatus.AWAITING_PAYMENT),
v.literal(BookingStatus.PAYMENT_FAILED),
v.literal(BookingStatus.SCHEDULED),
v.literal(BookingStatus.CANCELED),
v.literal(BookingStatus.COMPLETED)
), // Booking status
startTime: v.number(), // Start time of the booking (timestamp)
endTime: v.number(), // End time of the booking (timestamp)
createdAt: v.number(), // Creation time of the booking (timestamp)
updatedAt: v.number(), // Last updated time of the booking (timestamp)
})
.index("by_student", ["student", "startTime"])
.index("by_tutor", ["tutor", "startTime"])
.index("by_status", ["status"]), bookings: defineTable({
student: v.id("users"), // Reference to the student (user with role STUDENT)
tutor: v.id("users"), // Reference to the tutor (user with role TUTOR)
service: v.id("services"), // Reference to the service being booked
type: v.union(
v.literal(BookingType.FREE_MEETING),
v.literal(BookingType.LESSON)
), // Booking type
status: v.union(
v.literal(BookingStatus.AWAITING_TUTOR_CONFIRMATION),
v.literal(BookingStatus.AWAITING_STUDENT_CONFIRMATION),
v.literal(BookingStatus.AWAITING_PAYMENT),
v.literal(BookingStatus.PAYMENT_FAILED),
v.literal(BookingStatus.SCHEDULED),
v.literal(BookingStatus.CANCELED),
v.literal(BookingStatus.COMPLETED)
), // Booking status
startTime: v.number(), // Start time of the booking (timestamp)
endTime: v.number(), // End time of the booking (timestamp)
createdAt: v.number(), // Creation time of the booking (timestamp)
updatedAt: v.number(), // Last updated time of the booking (timestamp)
})
.index("by_student", ["student", "startTime"])
.index("by_tutor", ["tutor", "startTime"])
.index("by_status", ["status"]),I get a huge error, sorry for the spam
Type 'Query<{ document: { _id: Id<"bookings">; _creationTime: number; type: BookingType; tutor: Id<"users">; student: Id<"users">; service: Id<"services">; status: BookingStatus; startTime: number; endTime: number; createdAt: number; updatedAt: number; }; fieldPaths: ExtractFieldPaths<...> | "_id"; indexes: { ...; }; sear...' is missing the following properties from type 'QueryInitializer<{ document: { _id: Id<"bookings">; _creationTime: number; type: BookingType; tutor: Id<"users">; student: Id<"users">; service: Id<"services">; status: BookingStatus; startTime: number; endTime: number; createdAt: number; updatedAt: number; }; fieldPaths: ExtractFieldPaths<...> | "_id"; indexes: { ....': fullTableScan, withIndex, withSearchIndexts(2739)Type 'Query<{ document: { _id: Id<"bookings">; _creationTime: number; type: BookingType; tutor: Id<"users">; student: Id<"users">; service: Id<"services">; status: BookingStatus; startTime: number; endTime: number; createdAt: number; updatedAt: number; }; fieldPaths: ExtractFieldPaths<...> | "_id"; indexes: { ...; }; sear...' is missing the following properties from type 'QueryInitializer<{ document: { _id: Id<"bookings">; _creationTime: number; type: BookingType; tutor: Id<"users">; student: Id<"users">; service: Id<"services">; status: BookingStatus; startTime: number; endTime: number; createdAt: number; updatedAt: number; }; fieldPaths: ExtractFieldPaths<...> | "_id"; indexes: { ....': fullTableScan, withIndex, withSearchIndexts(2739)and all the args need to be marked with
!!