Skip to content

Commit

Permalink
refactor: lib search
Browse files Browse the repository at this point in the history
  • Loading branch information
ddaoxuan committed Oct 31, 2024
1 parent 8040e56 commit 1e9c5fc
Show file tree
Hide file tree
Showing 24 changed files with 642 additions and 488 deletions.
4 changes: 2 additions & 2 deletions starters/shopify-meilisearch/app/actions/product.actions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use server"

import { meilisearch } from "clients/search"
import { searchClient } from "lib/meilisearch/client"
import { env } from "env.mjs"
import { unstable_cache } from "next/cache"
import type { CommerceProduct } from "types"
Expand All @@ -14,7 +14,7 @@ export const searchProducts = unstable_cache(
hasMore: false,
}

const { hits, estimatedTotalHits } = await meilisearch.searchDocuments<CommerceProduct>({
const { hits, estimatedTotalHits } = await searchClient.searchDocuments<CommerceProduct>({
indexName: env.MEILISEARCH_PRODUCTS_INDEX,
query,
options: {
Expand Down
30 changes: 7 additions & 23 deletions starters/shopify-meilisearch/app/api/feed/sync/route.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { PlatformProduct } from "lib/shopify/types"
import { meilisearch } from "clients/search"
import { storefrontClient } from "clients/storefrontClient"
import { env } from "env.mjs"
import { compareHmac } from "utils/compare-hmac"
import { enrichProduct } from "utils/enrich-product"
import { deleteCategories, deleteProducts, updateCategories, updateProducts } from "lib/meilisearch"

type SupportedTopic = "products/update" | "products/delete" | "products/create" | "collections/update" | "collections/delete" | "collections/create"

Expand Down Expand Up @@ -54,21 +54,13 @@ async function handleCollectionTopics(topic: SupportedTopic, { id }: Record<stri
console.error(`Collection ${id} not found`)
return new Response(JSON.stringify({ message: "Collection not found" }), { status: 404, headers: { "Content-Type": "application/json" } })
}
await meilisearch.updateDocuments({
indexName: env.MEILISEARCH_CATEGORIES_INDEX,
documents: [{ ...collection, id: `${id}` }],
options: {
primaryKey: "id",
},
})

await updateCategories([{ ...collection, id: `${id}` }])

break

case "collections/delete":
await meilisearch.deleteDocuments({
indexName: env.MEILISEARCH_CATEGORIES_INDEX,
params: [id],
})
await deleteCategories([id])
break

default:
Expand All @@ -91,20 +83,12 @@ async function handleProductTopics(topic: SupportedTopic, { id }: Record<string,
}

const enrichedProduct = await enrichProduct(product, items)
await meilisearch.updateDocuments({
indexName: env.MEILISEARCH_PRODUCTS_INDEX,
documents: [normalizeProduct(enrichedProduct, id)],
options: {
primaryKey: "id",
},
})

await updateProducts([normalizeProduct(enrichedProduct, id)])

break
case "products/delete":
await meilisearch.deleteDocuments({
indexName: env.MEILISEARCH_PRODUCTS_INDEX,
params: [id],
})
await deleteProducts([id])
break

default:
Expand Down
27 changes: 9 additions & 18 deletions starters/shopify-meilisearch/app/api/reviews/ai-summary/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ import { generateObject } from "ai"
import z from "zod"
import { openai } from "@ai-sdk/openai"
import type { Review } from "lib/reviews/types"
import type { CommerceProduct } from "types"
import { meilisearch } from "clients/search"
import { env } from "env.mjs"
import { authenticate } from "utils/authenticate-api-route"
import { isOptIn, notifyOptIn } from "utils/opt-in"
import { unstable_noStore } from "next/cache"
import { isDemoMode } from "utils/demo-utils"
import { getAllProducts, getAllReviews, updateProducts } from "lib/meilisearch"

const summarySchema = z.object({
products: z.array(
Expand Down Expand Up @@ -46,25 +45,17 @@ export async function GET(req: Request) {
return new Response(JSON.stringify({ message: "Sorry, something went wrong" }), { status: 500 })
}

const [allReviews, allProducts] = await Promise.all([
meilisearch.getDocuments<Review>({
indexName: env.MEILISEARCH_REVIEWS_INDEX,
options: {
limit: 10000,
fields: ["body", "title", "product_handle", "rating"],
filter: "published=true AND hidden=false",
},
const [{ reviews }, allProducts] = await Promise.all([
getAllReviews({
fields: ["body", "title", "product_handle", "rating"],
filter: "published=true AND hidden=false",
}),
meilisearch.getDocuments<CommerceProduct>({
indexName: env.MEILISEARCH_PRODUCTS_INDEX,
options: {
limit: 10000,
fields: ["handle", "title", "id", "totalReviews"],
},
getAllProducts({
fields: ["handle", "title", "id", "totalReviews"],
}),
])

const mappedReviews: Record<string, Review[]> = allReviews?.results.reduce(
const mappedReviews: Record<string, Review[]> = reviews.reduce(
(acc, review) => {
const productHandle = review.product_handle
if (acc[productHandle]) {
Expand Down Expand Up @@ -126,7 +117,7 @@ export async function GET(req: Request) {
})
.filter(Boolean)

await meilisearch.updateDocuments<CommerceProduct>({ indexName: env.MEILISEARCH_PRODUCTS_INDEX, documents: updatedProducts, options: { primaryKey: "id" } })
await updateProducts(updatedProducts)

return new Response(JSON.stringify({ message: "Reviews synced" }), { status: 200 })
}
Expand Down
54 changes: 12 additions & 42 deletions starters/shopify-meilisearch/app/api/reviews/sync/route.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { unstable_noStore } from "next/cache"
import { meilisearch } from "clients/search"
import { reviewsClient } from "clients/reviews"
import { env } from "env.mjs"
import { authenticate } from "utils/authenticate-api-route"
import { isOptIn, notifyOptIn } from "utils/opt-in"
import type { Review } from "lib/reviews/types"
import type { CommerceProduct } from "types"
import { isDemoMode } from "utils/demo-utils"
import { getAllProducts, getAllReviews, updateProducts, updateReviews } from "lib/meilisearch"

export const maxDuration = 60

Expand All @@ -31,31 +29,23 @@ export async function GET(req: Request) {
return new Response(JSON.stringify({ message: "Sorry, something went wrong" }), { status: 500 })
}

const [allReviews, allProducts, allIndexReviews] = await Promise.all([
const [allReviews, { results: allProducts }, { reviews }] = await Promise.all([
reviewsClient.getAllProductReviews(),
meilisearch.getDocuments<CommerceProduct>({
indexName: env.MEILISEARCH_PRODUCTS_INDEX,
options: {
limit: 10000,
fields: ["handle", "totalReviews", "avgRating", "id"],
},
getAllProducts({
fields: ["handle", "title", "avgRating", "totalReviews"],
}),
meilisearch.getDocuments<Review>({
indexName: env.MEILISEARCH_REVIEWS_INDEX,
options: {
limit: 10000,
fields: ["updated_at", "id"],
},
getAllReviews({
fields: ["updated_at", "id"],
}),
])

const reviewsDelta = allReviews.filter((review) => {
const indexReview = allIndexReviews?.results.find((r) => r.id === review.id)
const indexReview = reviews?.find((r) => r.id === review.id)
return indexReview?.updated_at !== review.updated_at
})

const productTotalReviewsDelta = allProducts?.results
.map((product) => {
const productTotalReviewsDelta = allProducts
?.map((product) => {
const productReviews = allReviews.filter((review) => review.product_handle === product.handle && review.published && !review.hidden)
if (!!productReviews.length && productReviews.length !== product.totalReviews) {
const avgRating = productReviews.reduce((acc, review) => acc + review.rating, 0) / productReviews.length || 0
Expand All @@ -66,32 +56,12 @@ export async function GET(req: Request) {
})
.filter(Boolean)

if (!reviewsDelta.length && !productTotalReviewsDelta.length) {
if (!reviewsDelta.length && !productTotalReviewsDelta?.length) {
return new Response(JSON.stringify({ message: "Nothing to sync" }), { status: 200 })
}

!!reviewsDelta.length &&
(async () => {
meilisearch.updateDocuments({
indexName: env.MEILISEARCH_REVIEWS_INDEX!,
documents: reviewsDelta,
options: {
primaryKey: "id",
},
})
console.log("API/sync: Reviews synced", reviewsDelta.length)
})()
!!productTotalReviewsDelta.length &&
(async () => {
meilisearch.updateDocuments({
indexName: env.MEILISEARCH_PRODUCTS_INDEX,
documents: productTotalReviewsDelta,
options: {
primaryKey: "id",
},
})
console.log("API/sync:Products synced", productTotalReviewsDelta.length)
})()
!!reviewsDelta.length && updateReviews(reviewsDelta)
!!productTotalReviewsDelta?.length && updateProducts(productTotalReviewsDelta)

return new Response(JSON.stringify({ message: "All synced" }), { status: 200 })
}
15 changes: 5 additions & 10 deletions starters/shopify-meilisearch/app/category/clp/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { PlatformCollection } from "lib/shopify/types"
import { meilisearch } from "clients/search"
import { env } from "env.mjs"
import type { Metadata } from "next"
import { isDemoMode } from "utils/demo-utils"
import { CategoryView } from "views/category/category-view"
import { getCategories } from "lib/meilisearch"

export const revalidate = 86400
export const dynamic = "force-static"
Expand All @@ -22,15 +20,12 @@ export async function generateMetadata({ params }: CategoryPageProps): Promise<M
export async function generateStaticParams() {
if (isDemoMode()) return []

const { hits } = await meilisearch.searchDocuments<PlatformCollection>({
indexName: env.MEILISEARCH_CATEGORIES_INDEX,
options: {
limit: 50,
attributesToRetrieve: ["handle"],
},
const { results } = await getCategories({
limit: 50,
fields: ["handle"],
})

return hits.map(({ handle }) => ({ slug: handle }))
return results.map(({ handle }) => ({ slug: handle }))
}

export default async function CategoryPage({ params }: CategoryPageProps) {
Expand Down
2 changes: 1 addition & 1 deletion starters/shopify-meilisearch/app/favorites/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Suspense } from "react"
import { ProductCard } from "components/product-card"
import { Skeleton } from "components/ui/skeleton"
import { COOKIE_FAVORITES } from "constants/index"
import { getProduct } from "clients/search"
import { getProduct } from "lib/meilisearch"

export const revalidate = 86400

Expand Down
29 changes: 3 additions & 26 deletions starters/shopify-meilisearch/app/home/[bucket]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import { BUCKETS } from "constants/index"
import { AnnouncementBar } from "components/announcement-bar"
import { HeroSection } from "views/homepage/hero-section"
import { meilisearch } from "clients/search"
import { CommerceProduct } from "types"
import { env } from "env.mjs"
import type { Hits } from "meilisearch"
import { CategoriesSection } from "views/homepage/categories-section"
import { FeaturedProductsSection } from "views/homepage/featured-products-section"
import { PlatformCollection } from "lib/shopify/types"
import { getFeaturedProducts } from "lib/meilisearch"

export const revalidate = 86400

Expand All @@ -21,13 +17,13 @@ export default async function Homepage({ params: { bucket } }: { params: { bucke
b: "Shop the best Deals on Top Brands & Unique Finds",
}

const { products } = await fetchFeaturedData()
const results = await getFeaturedProducts()

return (
<div className="flex w-full flex-col">
<AnnouncementBar className="-order-2" />
<HeroSection className="-order-1 self-center md:-order-2" title={heroTitles[bucket]} />
<FeaturedProductsSection products={products} />
<FeaturedProductsSection products={results} />
<CategoriesSection />
</div>
)
Expand All @@ -36,22 +32,3 @@ export default async function Homepage({ params: { bucket } }: { params: { bucke
export async function generateStaticParams() {
return BUCKETS.HOME.map((bucket) => ({ bucket }))
}

const fetchFeaturedData = async () => {
const results = await meilisearch?.multiSearch({
queries: [
{
indexUid: env.MEILISEARCH_FEATURED_PRODUCTS_INDEX,
q: "",
limit: 6,
attributesToRetrieve: ["id", "title", "featuredImage", "minPrice", "variants", "avgRating", "totalReviews", "vendor", "handle"],
},
{ indexUid: env.MEILISEARCH_CATEGORIES_INDEX, q: "", limit: 4, attributesToRetrieve: ["id", "title", "handle"] },
],
})

return {
products: results[0].hits as Hits<CommerceProduct>,
categories: results[1].hits as Hits<PlatformCollection>,
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getProduct } from "clients/search"
import { getProduct } from "lib/meilisearch"
import { env } from "env.mjs"
import { Metadata } from "next"
import { Product, WithContext } from "schema-dts"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import { ImageResponse } from "next/og"
import { removeOptionsFromUrl } from "utils/product-options-utils"
import { env } from "env.mjs"
import { getProduct } from "clients/search"
import { getProduct } from "lib/meilisearch"

export const revalidate = 86400

Expand Down
14 changes: 4 additions & 10 deletions starters/shopify-meilisearch/app/product/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import { Suspense } from "react"
import { notFound } from "next/navigation"

import { getProduct, meilisearch } from "clients/search"

import { env } from "env.mjs"

import { isDemoMode } from "utils/demo-utils"
import { slugToName } from "utils/slug-name"
import { CurrencyType, mapCurrencyToSign } from "utils/map-currency-to-sign"
Expand All @@ -27,6 +23,7 @@ import { ReviewsSection } from "views/product/reviews-section"
import type { CommerceProduct } from "types"

import { generateJsonLd } from "./metadata"
import { getProduct, getProducts } from "lib/meilisearch"

export const revalidate = 86400
export const dynamic = "force-static"
Expand All @@ -39,12 +36,9 @@ interface ProductProps {
export async function generateStaticParams() {
if (isDemoMode()) return []

const { results } = await meilisearch.getDocuments<CommerceProduct>({
indexName: env.MEILISEARCH_PRODUCTS_INDEX,
options: {
limit: 50,
fields: ["handle"],
},
const { results } = await getProducts({
limit: 50,
fields: ["handle"],
})

return results.map(({ handle }) => ({ slug: handle }))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { makeKeywords } from "utils/make-keywords"
import { removeOptionsFromUrl } from "utils/product-options-utils"
import type { ProductReviewsPageProps } from "./page"
import { Metadata } from "next"
import { getProduct } from "clients/search"
import { getProduct } from "lib/meilisearch"
import { env } from "env.mjs"

export async function generateMetadata({ params: { slug } }: ProductReviewsPageProps): Promise<Metadata> {
Expand Down
2 changes: 1 addition & 1 deletion starters/shopify-meilisearch/app/reviews/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { notFound, redirect } from "next/navigation"

import { getProduct, getProductReviews } from "clients/search"
import { getProduct, getProductReviews } from "lib/meilisearch"

import { Breadcrumbs } from "components/breadcrumbs"

Expand Down
Loading

0 comments on commit 1e9c5fc

Please sign in to comment.