adjustments

rename search subscriber
fix: comments in medusa-interfaces/search-service.js
add: use cursor pagination when indexing all products to search engine
fix: emit product_id on product-variant creation
fix: move search API route under products/search
fix: use meilisearchService instead of searchService in plugin loader
This commit is contained in:
zakariaelas committed 2021-09-20 14:44:58 +01:00
1 parent 1444353b0a
commit 3a10e37377
9 files changed
+68 -63

No files matched your search

@@ -11,8 +11,8 @@ class SearchService extends BaseService {
/** /**
* Used to create an index * Used to create an index
* @param indexName {string} - the index name. * @param indexName {string} - the index name
* @param [options] {string} - the index name. * @param [options] {string} - the index name
* @return {Promise<{object}>} - returns response from search engine provider * @return {Promise<{object}>} - returns response from search engine provider
*/ */
createIndex(indexName, options) { createIndex(indexName, options) {
@@ -29,8 +29,8 @@ class SearchService extends BaseService {
} }
/** /**
* Used to index documents by the search engine provider. * Used to index documents by the search engine provider
* @param indexName {string} - the index name. * @param indexName {string} - the index name
* @param documents {Array.<Object>} - documents array to be indexed * @param documents {Array.<Object>} - documents array to be indexed
* @return {Promise<{object}>} - returns response from search engine provider * @return {Promise<{object}>} - returns response from search engine provider
*/ */
@@ -50,8 +50,8 @@ class SearchService extends BaseService {
/** /**
* Used to delete document * Used to delete document
* @param indexName {string} - the index name. * @param indexName {string} - the index name
* @param document_id {string} - the id of the document. * @param document_id {string} - the id of the document
* @return {Promise<{object}>} - returns response from search engine provider * @return {Promise<{object}>} - returns response from search engine provider
*/ */
deleteDocument(indexName, document_id) { deleteDocument(indexName, document_id) {
@@ -60,7 +60,7 @@ class SearchService extends BaseService {
/** /**
* Used to delete all documents * Used to delete all documents
* @param indexName {string} - the index name. * @param indexName {string} - the index name
* @return {Promise<{object}>} - returns response from search engine provider * @return {Promise<{object}>} - returns response from search engine provider
*/ */
deleteAllDocuments(indexName) { deleteAllDocuments(indexName) {
@@ -69,10 +69,10 @@ class SearchService extends BaseService {
/** /**
* Used to search for a document in an index * Used to search for a document in an index
* @param indexName {string} - the index name. * @param indexName {string} - the index name
* @param query {string} - the search query. * @param query {string} - the search query
* @param options {object} - any options passed to the request object other than the query and indexName * @param options {object} - any options passed to the request object other than the query and indexName
* e.g. pagination options, filtering options, etc. * e.g. pagination options, filtering options, etc
* @return {Promise<{object}>} - returns response from search engine provider * @return {Promise<{object}>} - returns response from search engine provider
*/ */
search(indexName, query, options) { search(indexName, query, options) {
@@ -81,7 +81,7 @@ class SearchService extends BaseService {
/** /**
* Used to update the settings of an index * Used to update the settings of an index
* @param indexName {string} - the index name. * @param indexName {string} - the index name
* @param settings {object} - settings object * @param settings {object} - settings object
* @return {Promise<{object}>} - returns response from search engine provider * @return {Promise<{object}>} - returns response from search engine provider
*/ */
@@ -2,11 +2,11 @@ const INDEX_NS = "medusa-commerce"
export default async (container, options) => { export default async (container, options) => {
try { try {
const searchService = container.resolve("searchService") const meilisearchService = container.resolve("meilisearchService")
await Promise.all( await Promise.all(
Object.entries(options.settings).map(([key, value]) => Object.entries(options.settings).map(([key, value]) =>
searchService.updateSettings(`${INDEX_NS}_${key}`, value) meilisearchService.updateSettings(`${INDEX_NS}_${key}`, value)
) )
) )
} catch (err) { } catch (err) {
@@ -15,7 +15,6 @@ import returnReasonRoutes from "./return-reasons"
import swapRoutes from "./swaps" import swapRoutes from "./swaps"
import variantRoutes from "./variants" import variantRoutes from "./variants"
import giftCardRoutes from "./gift-cards" import giftCardRoutes from "./gift-cards"
import searchRoutes from "./search"
const route = Router() const route = Router()
@@ -44,7 +43,6 @@ export default (app, container, config) => {
returnRoutes(route) returnRoutes(route)
giftCardRoutes(route) giftCardRoutes(route)
returnReasonRoutes(route) returnReasonRoutes(route)
searchRoutes(route)
return app return app
} }
@@ -7,6 +7,7 @@ export default app => {
app.use("/products", route) app.use("/products", route)
route.get("/", middlewares.wrap(require("./list-products").default)) route.get("/", middlewares.wrap(require("./list-products").default))
route.post("/search", middlewares.wrap(require("./search").default))
route.get("/:id", middlewares.wrap(require("./get-product").default)) route.get("/:id", middlewares.wrap(require("./get-product").default))
return app return app
@@ -1,11 +1,10 @@
import { Validator, MedusaError } from "medusa-core-utils" import { Validator, MedusaError } from "medusa-core-utils"
import { INDEX_NS } from "../../../../utils/index-ns" import ProductService from "../../../../services/product"
export default async (req, res) => { export default async (req, res) => {
const schema = Validator.object() const schema = Validator.object()
.keys({ .keys({
q: Validator.string().required(), q: Validator.string().required(),
indexName: Validator.string().required(),
}) })
.options({ allowUnknown: true }) .options({ allowUnknown: true })
@@ -20,7 +19,7 @@ export default async (req, res) => {
const searchService = req.scope.resolve("searchService") const searchService = req.scope.resolve("searchService")
const results = await searchService.search( const results = await searchService.search(
`${INDEX_NS}_${indexName}`, ProductService.IndexName,
q, q,
options options
) )
@@ -1,12 +0,0 @@
import { Router } from "express"
import middlewares from "../../../middlewares"
const route = Router()
export default app => {
app.use("/search", route)
route.post("/", middlewares.wrap(require("./search").default))
return app
}
@@ -203,6 +203,7 @@ class ProductVariantService extends BaseService {
.withTransaction(manager) .withTransaction(manager)
.emit(ProductVariantService.Events.CREATED, { .emit(ProductVariantService.Events.CREATED, {
id: result.id, id: result.id,
product_id: result.product_id,
}) })
return result return result
+49 -31
View File
@@ -749,41 +749,59 @@ class ProductService extends BaseService {
return product return product
} }
/**
* Loads all products into the search engine
*/
async loadIntoSearchEngine() { async loadIntoSearchEngine() {
if (this.searchService_.isDefault) return if (this.searchService_.isDefault) return
const products = await this.list( const TAKE = 20
{}, const totalCount = await this.count()
{ let iterCount = 0,
select: [ lastSeenId = ""
"id",
"title",
"subtitle",
"description",
"handle",
"is_giftcard",
"discountable",
"thumbnail",
"profile_id",
"collection_id",
"type_id",
"origin_country",
"created_at",
"updated_at",
],
relations: ["variants", "tags", "type", "collection"],
}
)
const flattenSkus = product => {
product.sku = flattenField(product.variants, "sku").filter(Boolean)
return product
}
const productsWithSkus = products.map(product => flattenSkus(product))
await this.searchService_.addDocuments( while (iterCount < totalCount) {
ProductService.IndexName, console.log({ lastSeenId })
productsWithSkus const products = await this.list(
) { id: { gte: lastSeenId } },
{
select: [
"id",
"title",
"subtitle",
"description",
"handle",
"is_giftcard",
"discountable",
"thumbnail",
"profile_id",
"collection_id",
"type_id",
"origin_country",
"created_at",
"updated_at",
],
relations: ["variants", "tags", "type", "collection"],
take: TAKE,
order: { id: "ASC" },
}
)
const flattenSkus = product => {
product.sku = flattenField(product.variants, "sku").filter(Boolean)
return product
}
const productsWithSkus = products.map(product => flattenSkus(product))
await this.searchService_.addDocuments(
ProductService.IndexName,
productsWithSkus
)
iterCount += TAKE
lastSeenId = products.at(-1).id
}
} }
} }
@@ -2,7 +2,7 @@ import ProductService from "../services/product"
import ProductVariantService from "../services/product-variant" import ProductVariantService from "../services/product-variant"
import { flattenField } from "../utils/flatten-field" import { flattenField } from "../utils/flatten-field"
class SearchSubscriber { class ProductSearchSubscriber {
constructor({ eventBusService, searchService, productService }, options) { constructor({ eventBusService, searchService, productService }, options) {
this.eventBus_ = eventBusService this.eventBus_ = eventBusService
@@ -86,4 +86,4 @@ class SearchSubscriber {
} }
} }
export default SearchSubscriber export default ProductSearchSubscriber