Coffee11
Coffee117mo ago

Dynamic query

Is this how we create dynamic query in convex?
let baseQuery = ctx.db
.query("property_listings")
.filter((q) => q.eq(q.field("listingType"), args.listingTypeId))

if (args?.minPrice !== undefined && args.minPrice >= 0) {
baseQuery = baseQuery.filter((q) =>
q.gte(q.field("price"), Number(args.minPrice))
);
}

if (args?.maxPrice !== undefined && args.maxPrice >= 0) {
baseQuery = baseQuery.filter((q) =>
q.lte(q.field("price"), Number(args.maxPrice))
);
}

const results = await baseQuery.order("desc").paginate(args.paginationOpts);

const updatedPage = await Promise.all(
results.page.map(async (propertyListing) => ({
...propertyListing,
}))
);
let baseQuery = ctx.db
.query("property_listings")
.filter((q) => q.eq(q.field("listingType"), args.listingTypeId))

if (args?.minPrice !== undefined && args.minPrice >= 0) {
baseQuery = baseQuery.filter((q) =>
q.gte(q.field("price"), Number(args.minPrice))
);
}

if (args?.maxPrice !== undefined && args.maxPrice >= 0) {
baseQuery = baseQuery.filter((q) =>
q.lte(q.field("price"), Number(args.maxPrice))
);
}

const results = await baseQuery.order("desc").paginate(args.paginationOpts);

const updatedPage = await Promise.all(
results.page.map(async (propertyListing) => ({
...propertyListing,
}))
);
it's working as expected but getting a typescript warning.
const { isLoading, results, loadMore } = usePaginatedQuery(
api.propertyListings.getPropertyListings, // <- on this part
{
listingTypeId: filters.listingTypeId as Id<"listing_types">,
properTypeId: filters.propertyTypeId as Id<"property_types">,
minPrice: filters.minPrice,
maxPrice: filters.maxPrice,
},
{
initialNumItems: 10,
}
);
const { isLoading, results, loadMore } = usePaginatedQuery(
api.propertyListings.getPropertyListings, // <- on this part
{
listingTypeId: filters.listingTypeId as Id<"listing_types">,
properTypeId: filters.propertyTypeId as Id<"property_types">,
minPrice: filters.minPrice,
maxPrice: filters.maxPrice,
},
{
initialNumItems: 10,
}
);
Argument of type 'FunctionReference<"query", "public", { minPrice?: number | undefined; maxPrice?: number | undefined; listingTypeId: Id<"listing_types">; properTypeId: Id<"property_types">; paginationOpts: { ...; }; }, { ...; }>' is not assignable to parameter of type 'PaginatedQueryReference'.
Types of property '_returnType' are incompatible.
Type '{ page: { listingType: string | undefined; propertyType: string | undefined; favorite: boolean; _id: Id<"property_listings">; _creationTime: number; pricePerSqm?: number | undefined; ... 22 more ...; description: string; }[]; ... 10 more ...; [Symbol.asyncIterator](): AsyncIterator<...>; }' is missing the following properties from type 'PaginationResult<any>': isDone, continueCursorts(2345)
Argument of type 'FunctionReference<"query", "public", { minPrice?: number | undefined; maxPrice?: number | undefined; listingTypeId: Id<"listing_types">; properTypeId: Id<"property_types">; paginationOpts: { ...; }; }, { ...; }>' is not assignable to parameter of type 'PaginatedQueryReference'.
Types of property '_returnType' are incompatible.
Type '{ page: { listingType: string | undefined; propertyType: string | undefined; favorite: boolean; _id: Id<"property_listings">; _creationTime: number; pricePerSqm?: number | undefined; ... 22 more ...; description: string; }[]; ... 10 more ...; [Symbol.asyncIterator](): AsyncIterator<...>; }' is missing the following properties from type 'PaginationResult<any>': isDone, continueCursorts(2345)
2 Replies
lee
lee7mo ago
the error message is saying the function's return type doesn't include all of the pagination fields. What does the query return? I would expect it to return {...results, page: updatedPage}
Coffee11
Coffee11OP7mo ago
Solve the issue now sorry it was the return it was the ...baseQuery before
return {
...results,
page: updatedPage,
};
return {
...results,
page: updatedPage,
};
this is the full code any idea or docs I can check how can I mix dynamic filters with full text search?
if (propertyType) {
const fieldToFilter =
propertyType.name === "Condominium" ? "floorSize" : "lotSize";

if (args?.minSqm !== undefined && args.minSqm >= 0) {
baseQuery = baseQuery.filter((q) =>
q.gte(q.field(fieldToFilter), Number(args.minSqm))
);
}

if (args?.maxSqm !== undefined && args.maxSqm >= 0) {
const maxSqmLimit = 999_999;
baseQuery = baseQuery.filter((q) =>
q.lte(q.field(fieldToFilter), Number(args.maxSqm || maxSqmLimit))
);
}
}

if (args?.search) {
baseQuery = baseQuery.withSearchIndex("search_descripton", (q) =>
q.search("description", args.search!)
);
}

const results = await baseQuery.order("desc").paginate(args.paginationOpts);

const updatedPage = await Promise.all(
results.page.map(async (propertyListing) => ({
...propertyListing,
listingType: (await ctx.db.get(propertyListing.listingType))?.name,
propertyType: (await ctx.db.get(propertyListing.propertyType))?.name,
favorite: (await favorite(propertyListing._id, user._id)) !== null,
}))
);

return {
...results,
page: updatedPage,
};
if (propertyType) {
const fieldToFilter =
propertyType.name === "Condominium" ? "floorSize" : "lotSize";

if (args?.minSqm !== undefined && args.minSqm >= 0) {
baseQuery = baseQuery.filter((q) =>
q.gte(q.field(fieldToFilter), Number(args.minSqm))
);
}

if (args?.maxSqm !== undefined && args.maxSqm >= 0) {
const maxSqmLimit = 999_999;
baseQuery = baseQuery.filter((q) =>
q.lte(q.field(fieldToFilter), Number(args.maxSqm || maxSqmLimit))
);
}
}

if (args?.search) {
baseQuery = baseQuery.withSearchIndex("search_descripton", (q) =>
q.search("description", args.search!)
);
}

const results = await baseQuery.order("desc").paginate(args.paginationOpts);

const updatedPage = await Promise.all(
results.page.map(async (propertyListing) => ({
...propertyListing,
listingType: (await ctx.db.get(propertyListing.listingType))?.name,
propertyType: (await ctx.db.get(propertyListing.propertyType))?.name,
favorite: (await favorite(propertyListing._id, user._id)) !== null,
}))
);

return {
...results,
page: updatedPage,
};
Error
Type 'OrderedQuery<{ document: { _id: Id<"property_listings">; _creationTime: number; pricePerSqm?: number | undefined; buildingName?: string | undefined; pricePerSqmFormatted?: string | undefined; ... 22 more ...; description: string; }; fieldPaths: ExtractFieldPaths<...> | "_id"; indexes: { ...; }; searchIndexes: { ...;...' is missing the following properties from type 'QueryInitializer<{ document: { _id: Id<"property_listings">; _creationTime: number; pricePerSqm?: number | undefined; buildingName?: string | undefined; pricePerSqmFormatted?: string | undefined; ... 22 more ...; description: string; }; fieldPaths: ExtractFieldPaths<...> | "_id"; indexes: { ...; }; searchIndexes: { ...': fullTableScan, withIndex, withSearchIndex, order
Type 'OrderedQuery<{ document: { _id: Id<"property_listings">; _creationTime: number; pricePerSqm?: number | undefined; buildingName?: string | undefined; pricePerSqmFormatted?: string | undefined; ... 22 more ...; description: string; }; fieldPaths: ExtractFieldPaths<...> | "_id"; indexes: { ...; }; searchIndexes: { ...;...' is missing the following properties from type 'QueryInitializer<{ document: { _id: Id<"property_listings">; _creationTime: number; pricePerSqm?: number | undefined; buildingName?: string | undefined; pricePerSqmFormatted?: string | undefined; ... 22 more ...; description: string; }; fieldPaths: ExtractFieldPaths<...> | "_id"; indexes: { ...; }; searchIndexes: { ...': fullTableScan, withIndex, withSearchIndex, order
Problem solve ❤️

Did you find this page helpful?