
Join the Conversation!
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
"Please login to view comments"
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
So far, we're only passing the to the method in .
In this lesson, we'll learn how to filter the products based on the and , and fields.
Let's open up our .
We should already be passing the page to our method, but now let's pass the rest of our searchParams:
page.tsx
export default async function Page({
searchParams,
}: {
searchParams: {
name: string;
category: string;
minPrice: string;
page: string;
};
}) {
const page = parseInt(searchParams.page) || 1;
// pass the rest of the searchParams
const products = await getProducts({ ...searchParams, page });
...
}
Now let's add those props to our method:
products.ts
export async function getProducts({
page = 1,
name,
minPrice,
category,
}: {
page?: number;
name?: string;
minPrice?: string;
category?: string;
}) {
const resultsPerPage = 5;
const skip = (page - 1) * resultsPerPage;
...
}
We now have access to the , , and filters in our method.
Whenever the URL changes, we'll pass the filters to the method, and get updated results.
Let's start by filtering the products by name.
In our method, we'll add a object to our method.
We'll be filtering by the field, and we'll use the filter to check if the field contains the filter.
products.ts;
const products = await prisma.product.findMany({
where: {
// filter by name
name: {
contains: name,
mode: "insensitive",
},
},
skip,
take: resultsPerPage,
});
We're using the filter to check if the field contains the filter.
We're also using the option to make the search case-insensitive.
Remember in SQL? This is similar to that. We're checking if the field contains the passed in from the URL anywhere in the string.
Adding our category filter is similar to the name filter, but we'll need to make some considerations.
For starters, the default value for the filter is the string "all", which means we want to show all products regardless of their category.
This is where dynamically building our object comes in handy:
products.ts;
const where: any = {};
if (name) {
where.name = {
contains: name,
mode: "insensitive",
};
}
if (category && category !== "all") {
where.category = {
equals: category,
};
}
const allProducts = await prisma.product.findMany({
include: {
images: true,
reviews: true,
},
where,
skip,
take: resultsPerPage,
});
There are many ways to build the object. This is just one way to do it.
Another popular way is to use the spread operator to build the object dynamically:
products.ts;
const filterCategory = category !== "all";
const allProducts = await prisma.product.findMany({
include: {
images: true,
reviews: true,
},
where: {
name: {
contains: name,
mode: "insensitive",
},
...(filterCategory && { category }),
},
skip,
take: resultsPerPage,
});
This method shows us creating a variable to check if we should filter by category. If we should, we add the filter to the object.
This is a more concise way to build the object, but can be harder to read for beginners, and harder to maintain as the object grows.
We'll now be
Let's add a filter to our method, here's the final function.
products.ts;
export async function getProducts({
page = 1,
name,
minPrice,
category,
}: {
page?: number;
name?: string;
minPrice?: string;
category?: string;
}) {
const resultsPerPage = 5;
const skip = (page - 1) * resultsPerPage;
const filterCategory = category !== "all";
try {
const allProducts = await prisma.product.findMany({
include: {
images: true,
reviews: true,
},
where: {
name: {
contains: name,
mode: "insensitive",
},
...(filterCategory && { category }),
...(minPrice && {
price: {
gte: parseInt(minPrice),
},
}),
},
skip,
take: resultsPerPage,
});
const products = allProducts.map((product) => ({
...product,
rating:
Math.floor(
product.reviews.reduce((acc, review) => acc + review.rating, 0) /
product.reviews.length,
) || 0,
image: product.images[0]?.url,
}));
return products;
} catch (error) {
console.error("Error fetching products:", error);
return [];
}
}
We're using the filter to check if the field is greater than or equal to the filter.
Remember in SQL? This is similar to that. We're checking if the field is greater than or equal to the passed in from the URL.
There are many other filters we can use, such as (less than), (less than or equal to), (greater than), (greater than or equal to), (in an array), (not equal to), and many more.
Experiment and see how they work!
Let's break down this addition to our filter:
//
// dynamically build the where object.
// if we have a 'minPrice' filter, add it to the where object
...(minPrice && {
price: { // filter by price
gte: parseInt(minPrice), // price must be 'greater than or equal to' the minPrice
},
}),
We've learned how to filter our products by , , and .