more adjustments

move indexing logic to plugin
remove loadToSearchEngine from ProductService
adjust medusa core accordingly
This commit is contained in:
zakariaelas
2021-09-21 13:14:08 +01:00
parent 3a10e37377
commit c67ca16a9b
7 changed files with 161 additions and 151 deletions

View File

@@ -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)
}

View File

@@ -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

View File

@@ -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,
}
}

View File

@@ -7,7 +7,4 @@ export default async ({ container }) => {
)
return
}
const productService = container.resolve("productService")
await productService.loadIntoSearchEngine()
}

View File

@@ -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

View File

@@ -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

View File

@@ -1,3 +0,0 @@
export const flattenField = (list, field) => {
return list.map(el => el[field])
}