From c67ca16a9b4b05b528fee0d53d5242fdb8ab985b Mon Sep 17 00:00:00 2001 From: zakariaelas Date: Tue, 21 Sep 2021 13:14:08 +0100 Subject: [PATCH] more adjustments move indexing logic to plugin remove loadToSearchEngine from ProductService adjust medusa core accordingly --- .../src/loaders/index.js | 51 +++++++++++ .../src/subscribers/product-search.js | 91 +++++++++++++++++++ .../src/utils/transform-products.js | 19 ++++ packages/medusa/src/loaders/search-index.js | 3 - packages/medusa/src/services/product.js | 56 ------------ .../medusa/src/subscribers/product-search.js | 89 ------------------ packages/medusa/src/utils/flatten-field.js | 3 - 7 files changed, 161 insertions(+), 151 deletions(-) create mode 100644 packages/medusa-plugin-meilisearch/src/subscribers/product-search.js create mode 100644 packages/medusa-plugin-meilisearch/src/utils/transform-products.js delete mode 100644 packages/medusa/src/subscribers/product-search.js delete mode 100644 packages/medusa/src/utils/flatten-field.js diff --git a/packages/medusa-plugin-meilisearch/src/loaders/index.js b/packages/medusa-plugin-meilisearch/src/loaders/index.js index 16388cf689..33e24d2468 100644 --- a/packages/medusa-plugin-meilisearch/src/loaders/index.js +++ b/packages/medusa-plugin-meilisearch/src/loaders/index.js @@ -1,5 +1,54 @@ +import { transformProduct } from "../utils/transform-products" + const INDEX_NS = "medusa-commerce" +async function loadIntoSearchEngine(container) { + const meilisearchService = container.resolve("meilisearchService") + const productService = container.resolve("productService") + + const TAKE = 20 + const totalCount = await productService.count() + let iterCount = 0, + lastSeenId = "prod" + + while (iterCount < totalCount) { + const products = await productService.list( + { id: { gt: 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 transformedProducts = products.map(transformProduct) + + await meilisearchService.addDocuments( + `medusa-commerce_products`, + transformedProducts + ) + + iterCount += products.length + lastSeenId = products.at(-1).id + } +} + export default async (container, options) => { try { const meilisearchService = container.resolve("meilisearchService") @@ -9,6 +58,8 @@ export default async (container, options) => { meilisearchService.updateSettings(`${INDEX_NS}_${key}`, value) ) ) + + await loadIntoSearchEngine(container) } catch (err) { console.log(err) } diff --git a/packages/medusa-plugin-meilisearch/src/subscribers/product-search.js b/packages/medusa-plugin-meilisearch/src/subscribers/product-search.js new file mode 100644 index 0000000000..aa932afadc --- /dev/null +++ b/packages/medusa-plugin-meilisearch/src/subscribers/product-search.js @@ -0,0 +1,91 @@ +import { transformProduct } from "../utils/transform-products" + +class ProductSearchSubscriber { + constructor( + { eventBusService, meilisearchService, productService }, + options + ) { + this.eventBus_ = eventBusService + + this.meilisearchService_ = meilisearchService + + this.productService_ = productService + + this.productIndexName = "medusa-commerce_products" + + this.eventBus_.subscribe("product.created", this.handleProductCreation) + + this.eventBus_.subscribe("product.updated", this.handleProductUpdate) + + this.eventBus_.subscribe("product.deleted", this.handleProductDeletion) + + this.eventBus_.subscribe( + "product-variant.created", + this.handleProductVariantChange + ) + + this.eventBus_.subscribe( + "product-variant.updated", + this.handleProductVariantChange + ) + + this.eventBus_.subscribe( + "product-variant.deleted", + this.handleProductVariantChange + ) + } + + handleProductCreation = async (data) => { + const product = await this.retrieveProduct_(data.id) + await this.meilisearchService_.addDocuments(this.productIndexName, [ + product, + ]) + } + + retrieveProduct_ = async (product_id) => { + const product = await this.productService_.retrieve(product_id, { + 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"], + }) + const transformedProduct = transformProduct(product) + return transformedProduct + } + + handleProductUpdate = async (data) => { + const product = await this.retrieveProduct_(data.id) + await this.meilisearchService_.addDocuments(this.productIndexName, [ + product, + ]) + } + + handleProductDeletion = async (data) => { + await this.meilisearchService_.deleteDocument( + this.productIndexName, + data.id + ) + } + + handleProductVariantChange = async (data) => { + const product = await this.retrieveProduct_(data.product_id) + await this.meilisearchService_.addDocuments(this.productIndexName, [ + product, + ]) + } +} + +export default ProductSearchSubscriber diff --git a/packages/medusa-plugin-meilisearch/src/utils/transform-products.js b/packages/medusa-plugin-meilisearch/src/utils/transform-products.js new file mode 100644 index 0000000000..c50302d444 --- /dev/null +++ b/packages/medusa-plugin-meilisearch/src/utils/transform-products.js @@ -0,0 +1,19 @@ +const keys = ["sku", "title", "upc", "ean", "mid_code", "hs_code"] +const prefix = `variant` + +export const transformProduct = (product) => { + const initialObj = keys.reduce((obj, key) => { + obj[`${prefix}_${key}`] = [] + return obj + }, {}) + + const flattenedFields = product.variants.reduce((obj, variant) => { + keys.forEach((k) => variant[k] && obj[`${prefix}_${k}`].push(variant[k])) + return obj + }, initialObj) + + return { + ...product, + ...flattenedFields, + } +} diff --git a/packages/medusa/src/loaders/search-index.js b/packages/medusa/src/loaders/search-index.js index 9dfa81ee24..dac541fa43 100644 --- a/packages/medusa/src/loaders/search-index.js +++ b/packages/medusa/src/loaders/search-index.js @@ -7,7 +7,4 @@ export default async ({ container }) => { ) return } - - const productService = container.resolve("productService") - await productService.loadIntoSearchEngine() } diff --git a/packages/medusa/src/services/product.js b/packages/medusa/src/services/product.js index e06e13068f..f631664a92 100644 --- a/packages/medusa/src/services/product.js +++ b/packages/medusa/src/services/product.js @@ -2,7 +2,6 @@ import _ from "lodash" import { MedusaError } from "medusa-core-utils" import { BaseService } from "medusa-interfaces" import { Brackets } from "typeorm" -import { flattenField } from "../utils/flatten-field" import { INDEX_NS } from "../utils/index-ns" /** @@ -748,61 +747,6 @@ class ProductService extends BaseService { // const final = await this.runDecorators_(decorated) return product } - - /** - * Loads all products into the search engine - */ - - async loadIntoSearchEngine() { - if (this.searchService_.isDefault) return - - const TAKE = 20 - const totalCount = await this.count() - let iterCount = 0, - lastSeenId = "" - - while (iterCount < totalCount) { - console.log({ lastSeenId }) - 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 - } - } } export default ProductService diff --git a/packages/medusa/src/subscribers/product-search.js b/packages/medusa/src/subscribers/product-search.js deleted file mode 100644 index 9781c8220a..0000000000 --- a/packages/medusa/src/subscribers/product-search.js +++ /dev/null @@ -1,89 +0,0 @@ -import ProductService from "../services/product" -import ProductVariantService from "../services/product-variant" -import { flattenField } from "../utils/flatten-field" - -class ProductSearchSubscriber { - constructor({ eventBusService, searchService, productService }, options) { - this.eventBus_ = eventBusService - - this.searchService_ = searchService - - this.productService_ = productService - - this.eventBus_.subscribe( - ProductService.Events.CREATED, - this.handleProductCreation - ) - - this.eventBus_.subscribe( - ProductService.Events.UPDATED, - this.handleProductUpdate - ) - - this.eventBus_.subscribe( - ProductService.Events.DELETED, - this.handleProductDeletion - ) - - this.eventBus_.subscribe( - ProductVariantService.Events.CREATED, - this.handleProductVariantChange - ) - - this.eventBus_.subscribe( - ProductVariantService.Events.UPDATED, - this.handleProductVariantChange - ) - - this.eventBus_.subscribe( - ProductVariantService.Events.DELETED, - this.handleProductVariantChange - ) - } - - handleProductCreation = async data => { - const product = await this.retrieveProduct_(data.id) - await this.searchService_.addDocuments(ProductService.IndexName, [product]) - } - - retrieveProduct_ = async product_id => { - const product = await this.productService_.retrieve(product_id, { - 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"], - }) - const skus = flattenField(product.variants, "sku").filter(Boolean) - product.sku = skus - return product - } - - handleProductUpdate = async data => { - const product = await this.retrieveProduct_(data.id) - await this.searchService_.addDocuments(ProductService.IndexName, [product]) - } - - handleProductDeletion = async data => { - await this.searchService_.deleteDocument(ProductService.IndexName, data.id) - } - - handleProductVariantChange = async data => { - const product = await this.retrieveProduct_(data.product_id) - await this.searchService_.addDocuments(ProductService.IndexName, [product]) - } -} - -export default ProductSearchSubscriber diff --git a/packages/medusa/src/utils/flatten-field.js b/packages/medusa/src/utils/flatten-field.js deleted file mode 100644 index 2f6998ed09..0000000000 --- a/packages/medusa/src/utils/flatten-field.js +++ /dev/null @@ -1,3 +0,0 @@ -export const flattenField = (list, field) => { - return list.map(el => el[field]) -}