Poradnik dotyczący integracji Meilisearch z Medusa.js
Autor Viktor Holik
Autor Viktor Holik
Około rok temu ja i mój zespół rozpoczęliśmy projekt Medusa eCommerce, który wymagał zaawansowanych możliwości filtrowania produktów. Potrzebowaliśmy funkcjonalności takich jak filtrowanie predykcyjne na podstawie kategorii lub atrybutów, wyszukiwanie pełnotekstowe, tolerancję błędów oraz trafne wyniki wyszukiwania. Tworzenie tych funkcji od podstaw w PostgreSQL lub podobnych bazach danych jest czasochłonne i wymaga znacznej wiedzy specjalistycznej.
Na szczęście istnieje rozwiązanie open source, które doskonale spełnia te wymagania — Meilisearch.
W tym poradniku opiszę, jak działa Meilisearch i przedstawię praktyczne przykłady jego integracji z Medusa.js. Zaczynajmy!
Na początek zobaczmy, jak Medusa integruje się z API Meilisearch.
Gdy backend się uruchamia, Medusa używa loadera, który masowo dodaje produkty za pomocą API Meilisearch. Następnie wszelkie zmiany, usunięcia czy tworzenie produktów są zarządzane przez subskrybenta Medusa, który odpowiednio obsługuje te aktualizacje.
Aby zacząć używać Meilisearch w swoim projekcie Medusa, dołącz medusa-plugin-meilisearch do swojego medusa-config.js:
const plugins = [
// ...
{
resolve: `medusa-plugin-meilisearch`,
options: {
config: {
host: process.env.MEILISEARCH_HOST,
apiKey: process.env.MEILISEARCH_API_KEY,
},
settings: {
// ustawienia indeksu...
},
},
},
]
W tym poradniku używam domyślnej konfiguracji wtyczki, z wyjątkiem filterableAttributes i sortableAttributes.
Indeks w Meilisearch to grupa dokumentów z powiązanymi ustawieniami. Określając klucz indeksu, można skonfigurować specyficzne ustawienia dla tego indeksu:
{
resolve: `medusa-plugin-meilisearch`,
options: {
config: {
host: process.env.MEILISEARCH_HOST,
apiKey: process.env.MEILISEARCH_API_KEY,
},
settings: {
products: {
indexSettings: {
filterableAttributes: ["categories.handle", "variants.prices.amount", "variants.prices.currency_code"],
sortableAttributes: ["title", "variants.prices.amount"],
searchableAttributes: ["title", "description", "variant_sku"],
displayedAttributes: ["*"],
primaryKey: "id",
transformer: (product) => ({
// Niestandardowa logika transformacji
})
},
},
},
},
},
Ustawiając filterableAttributes, umożliwiasz filtrowanie dokumentów za pomocą tych kluczy. Pamiętaj, że dodaje to również wyszukiwanie fasetowe (przewidywanie filtrów). Funkcja transformująca pozwala modyfikować dane w preferowanym formacie przed ich aktualizacją w Meilisearch. Każdy klucz w indexSettings jest opcjonalny.
Zainicjujmy naszego klienta Meilisearch. Zainstaluj pakiet Meilisearch i dodaj następujący kod w folderze z narzędziami:
Pamiętaj, aby nie ujawniać publicznie klucza API.
// lib/meilisearch
import { MeiliSearch } from 'meilisearch'
export const meilisearchClient = new MeiliSearch({
host: process.env.MEILISEARCH_HOST!,
apiKey: process.env.MEILISEARCH_API_KEY!,
})
Stwórzmy teraz funkcję narzędziową obsługującą filtrowanie produktów:
// lib/meilisearch
type FiltersQuery = {
categories?: string[]
orderBy?: string
order?: 'asc' | 'desc'
page?: number
minPrice?: number
maxPrice?: number
query?: string
currencyCode?: string
}
const PAGE_SIZE = 15
export async function getProductsFromMeilisearch({
categories,
maxPrice,
minPrice,
orderBy,
order = 'asc',
page = 1,
query,
currencyCode = 'usd',
}: FiltersQuery) {
// Aby wdrożyć...
}
Meilisearch wykorzystuje składnię podobną do SQL do filtrowania produktów, dzięki czemu jest prosty w użyciu. Opracujmy funkcję filtrującą produkty na podstawie określonych parametrów.
export async function getProductsFromMeilisearch({
categories,
maxPrice,
minPrice,
orderBy,
order = 'asc',
page = 1,
query,
currencyCode = 'usd',
}: FiltersQuery) {
const offset = (page - 1) * PAGE_SIZE
const queries: string[] = []
if (categories) {
queries.push(`categories.handle IN [${categories.join(', ')}]`)
}
if (minPrice) {
queries.push(
`(variants.prices.amount >= ${minPrice} AND variants.prices.currency_code = "${currencyCode}")`
)
}
if (maxPrice) {
queries.push(
`(variants.prices.amount <= ${maxPrice} AND variants.prices.currency_code = "${currencyCode}")`
)
}
const result = await meilisearchClient.index('products').search(query, {
limit: PAGE_SIZE,
offset: offset,
sort: orderBy ? [`${orderBy}:${order}`] : undefined,
filter: queries.join(' AND '),
facets: ['categories.handle'],
})
return result
}
Teraz powinieneś być w stanie zobaczyć swoje przefiltrowane produkty oraz aspekty w odpowiedziach. Dzięki tej funkcji możesz bezproblemowo zaimplementować paginację, filtrowanie, predykcyjne filtrowanie i wiele więcej.
{
hits: [
{
id: 'cool-t-shirt',
title: 'Medusa T-Shirt',
description: 'Reimagine the feeling of a classic T-shirt. With our cotton T-shirts, everyday essentials no longer have to be ordinary.',
categories: [Array],
handle: 't-shirt',
subtitle: null,
is_giftcard: false,
weight: 400,
images: [Array],
options: [Array],
variants: [Array],
tags_value: [],
variant_sku: [],
variant_title: [Array],
variant_upc: [],
variant_ean: [],
variant_mid_code: [],
variant_hs_code: [],
variant_options: [],
variant_options_value: [Array]
}
],
query: 'T shirt',
processingTimeMs: 0,
limit: 15,
offset: 0,
estimatedTotalHits: 1,
facetDistribution: { 'categories.handle': { 't-shirt': 1 } },
facetStats: {}
}
Celem tego artykułu jest dostarczenie podstawowej wiedzy na temat używania Meilisearch z Medusa.js. Zalecam rozpoczęcie od potrzeb twojego projektu i eksperymentowanie z tymi integracjami. Mam nadzieję, że ten przewodnik okaże się pomocny.
Wtyczka Medusa Tolgee do obsługi wielu języków integruje platformę eCommerce Medusa z Tolgee, platformą lokalizacyjną typu open-source, oferując łatwe rozwiązanie do zarządzania tłumaczeniami...
Ten przewodnik pokazuje, jak skonfigurować projekt Medusa z wykorzystaniem Autopay jako wybranym procesorem płatności, przy użyciu wtyczki medusa-payment-autopay.