Skip to content

Commit 9725bff

Browse files
fix(index): logical operators (medusajs#13137)
1 parent a527087 commit 9725bff

File tree

11 files changed

+375
-127
lines changed

11 files changed

+375
-127
lines changed

.changeset/eleven-apricots-look.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@medusajs/index": patch
3+
"@medusajs/link-modules": patch
4+
---
5+
6+
fix(index): handle $and and $or operators

integration-tests/modules/__tests__/index/query-index.spec.ts

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
ContainerRegistrationKeys,
77
defaultCurrencies,
88
defineLink,
9+
Modules,
910
} from "@medusajs/utils"
1011
import { setTimeout } from "timers/promises"
1112
import {
@@ -35,6 +36,7 @@ async function populateData(api: any) {
3536
origin_country: "USA",
3637
shipping_profile_id: shippingProfile.id,
3738
options: [{ title: "Denominations", values: ["100"] }],
39+
material: "test-material",
3840
variants: [
3941
{
4042
title: `Test variant 1`,
@@ -61,6 +63,7 @@ async function populateData(api: any) {
6163
status: "published",
6264
shipping_profile_id: shippingProfile.id,
6365
options: [{ title: "Colors", values: ["Red"] }],
66+
material: "extra-material",
6467
variants: new Array(2).fill(0).map((_, i) => ({
6568
title: `extra variant ${i}`,
6669
sku: `extra-variant-${i}`,
@@ -81,9 +84,16 @@ async function populateData(api: any) {
8184
},
8285
]
8386

84-
await api.post("/admin/products/batch", { create: payload }, adminHeaders)
87+
const response = await api.post(
88+
"/admin/products/batch",
89+
{ create: payload },
90+
adminHeaders
91+
)
92+
const products = response.data.created
8593

8694
await setTimeout(4000)
95+
96+
return products
8797
}
8898

8999
process.env.ENABLE_INDEX_MODULE = "true"
@@ -117,7 +127,22 @@ medusaIntegrationTestRunner({
117127
})
118128

119129
it("should use query.index to query the index module and hydrate the data", async () => {
120-
await populateData(api)
130+
const products = await populateData(api)
131+
132+
const brandModule = appContainer.resolve("brand")
133+
const link = appContainer.resolve(ContainerRegistrationKeys.LINK)
134+
const brand = await brandModule.createBrands({
135+
name: "Medusa Brand",
136+
})
137+
138+
await link.create({
139+
[Modules.PRODUCT]: {
140+
product_id: products.find((p) => p.title === "Extra product").id,
141+
},
142+
brand: {
143+
brand_id: brand.id,
144+
},
145+
})
121146

122147
const query = appContainer.resolve(
123148
ContainerRegistrationKeys.QUERY
@@ -132,6 +157,8 @@ medusaIntegrationTestRunner({
132157
"description",
133158
"status",
134159
"title",
160+
"brand.name",
161+
"brand.id",
135162
"variants.sku",
136163
"variants.barcode",
137164
"variants.material",
@@ -142,8 +169,28 @@ medusaIntegrationTestRunner({
142169
"variants.inventory_items.inventory.description",
143170
],
144171
filters: {
145-
"variants.sku": { $like: "%-1" },
146-
"variants.prices.amount": { $gt: 30 },
172+
$and: [
173+
{ status: "published" },
174+
{ material: { $ilike: "%material%" } },
175+
{
176+
$or: [
177+
{
178+
brand: {
179+
name: { $ilike: "%brand" },
180+
},
181+
},
182+
{ title: { $ilike: "%duct%" } },
183+
],
184+
},
185+
{
186+
variants: {
187+
$and: [
188+
{ sku: { $like: "%-1" } },
189+
{ "prices.amount": { $gt: 30 } },
190+
],
191+
},
192+
},
193+
],
147194
},
148195
pagination: {
149196
take: 10,
@@ -171,6 +218,10 @@ medusaIntegrationTestRunner({
171218
description: "extra description",
172219
title: "Extra product",
173220
status: "published",
221+
brand: {
222+
id: expect.any(String),
223+
name: "Medusa Brand",
224+
},
174225
variants: [
175226
{
176227
sku: "extra-variant-0",
@@ -247,6 +298,7 @@ medusaIntegrationTestRunner({
247298
description: "test-product-description",
248299
title: "Test Product",
249300
status: "published",
301+
brand: undefined,
250302
variants: [
251303
{
252304
sku: "test-variant-1",

integration-tests/modules/medusa-config.js renamed to integration-tests/modules/medusa-config.ts

Lines changed: 89 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { defineConfig } from "@medusajs/utils"
2+
13
const { Modules } = require("@medusajs/utils")
24

35
const DB_HOST = process.env.DB_HOST
@@ -35,7 +37,7 @@ const customFulfillmentProviderCalculated = {
3537
id: "test-provider-calculated",
3638
}
3739

38-
module.exports = {
40+
module.exports = defineConfig({
3941
admin: {
4042
disable: true,
4143
},
@@ -51,11 +53,13 @@ module.exports = {
5153
featureFlags: {
5254
medusa_v2: enableMedusaV2,
5355
},
54-
modules: {
55-
testingModule: {
56+
modules: [
57+
{
58+
key: "testingModule",
5659
resolve: "__tests__/__fixtures__/testing-module",
5760
},
58-
[Modules.AUTH]: {
61+
{
62+
key: "auth",
5963
resolve: "@medusajs/auth",
6064
options: {
6165
providers: [
@@ -66,62 +70,107 @@ module.exports = {
6670
],
6771
},
6872
},
69-
[Modules.USER]: {
73+
{
74+
key: Modules.USER,
7075
scope: "internal",
7176
resolve: "@medusajs/user",
7277
options: {
7378
jwt_secret: "test",
7479
},
7580
},
76-
[Modules.CACHE]: {
81+
{
82+
key: Modules.CACHE,
7783
resolve: "@medusajs/cache-inmemory",
7884
options: { ttl: 0 }, // Cache disabled
7985
},
80-
[Modules.LOCKING]: true,
81-
[Modules.STOCK_LOCATION]: {
86+
{
87+
key: Modules.LOCKING,
88+
resolve: "@medusajs/locking",
89+
},
90+
{
91+
key: Modules.STOCK_LOCATION,
8292
resolve: "@medusajs/stock-location",
8393
options: {},
8494
},
85-
[Modules.INVENTORY]: {
95+
{
96+
key: Modules.INVENTORY,
8697
resolve: "@medusajs/inventory",
8798
options: {},
8899
},
89-
[Modules.PRODUCT]: true,
90-
[Modules.PRICING]: true,
91-
[Modules.PROMOTION]: true,
92-
[Modules.REGION]: true,
93-
[Modules.CUSTOMER]: true,
94-
[Modules.SALES_CHANNEL]: true,
95-
[Modules.CART]: true,
96-
[Modules.WORKFLOW_ENGINE]: true,
97-
[Modules.API_KEY]: true,
98-
[Modules.STORE]: true,
99-
[Modules.TAX]: {
100+
{
101+
key: Modules.PRODUCT,
102+
resolve: "@medusajs/product",
103+
},
104+
{
105+
key: Modules.PRICING,
106+
resolve: "@medusajs/pricing",
107+
},
108+
{
109+
key: Modules.PROMOTION,
110+
resolve: "@medusajs/promotion",
111+
},
112+
{
113+
key: Modules.REGION,
114+
resolve: "@medusajs/region",
115+
},
116+
{
117+
key: Modules.CUSTOMER,
118+
resolve: "@medusajs/customer",
119+
},
120+
{
121+
key: Modules.SALES_CHANNEL,
122+
resolve: "@medusajs/sales-channel",
123+
},
124+
{
125+
key: Modules.CART,
126+
resolve: "@medusajs/cart",
127+
},
128+
{
129+
key: Modules.WORKFLOW_ENGINE,
130+
resolve: "@medusajs/workflow-engine-inmemory",
131+
},
132+
{
133+
key: Modules.API_KEY,
134+
resolve: "@medusajs/api-key",
135+
},
136+
{
137+
key: Modules.STORE,
138+
resolve: "@medusajs/store",
139+
},
140+
{
141+
key: Modules.TAX,
100142
resolve: "@medusajs/tax",
101143
options: {
102144
providers: [customTaxProviderRegistration],
103145
},
104146
},
105-
[Modules.CURRENCY]: true,
106-
[Modules.ORDER]: true,
107-
[Modules.PAYMENT]: {
147+
{
148+
key: Modules.CURRENCY,
149+
resolve: "@medusajs/currency",
150+
},
151+
{
152+
key: Modules.ORDER,
153+
resolve: "@medusajs/order",
154+
},
155+
{
156+
key: Modules.PAYMENT,
108157
resolve: "@medusajs/payment",
109-
/** @type {import('@medusajs/payment').PaymentModuleOptions}*/
110158
options: {
111159
providers: [customPaymentProvider],
112160
},
113161
},
114-
[Modules.FULFILLMENT]: {
115-
/** @type {import('@medusajs/fulfillment').FulfillmentModuleOptions} */
162+
{
163+
key: Modules.FULFILLMENT,
164+
resolve: "@medusajs/fulfillment",
116165
options: {
117166
providers: [
118167
customFulfillmentProvider,
119168
customFulfillmentProviderCalculated,
120169
],
121170
},
122171
},
123-
[Modules.NOTIFICATION]: {
124-
/** @type {import('@medusajs/types').LocalNotificationServiceOptions} */
172+
{
173+
key: Modules.NOTIFICATION,
125174
options: {
126175
providers: [
127176
{
@@ -135,10 +184,15 @@ module.exports = {
135184
],
136185
},
137186
},
138-
[Modules.INDEX]: process.env.ENABLE_INDEX_MODULE
139-
? {
140-
resolve: "@medusajs/index",
141-
}
142-
: false,
143-
},
144-
}
187+
{
188+
key: Modules.INDEX,
189+
resolve: "@medusajs/index",
190+
disable: process.env.ENABLE_INDEX_MODULE !== "true",
191+
},
192+
{
193+
key: "brand",
194+
resolve: "src/modules/brand",
195+
disable: process.env.ENABLE_INDEX_MODULE !== "true",
196+
},
197+
],
198+
})
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import ProductModule from "@medusajs/medusa/product"
2+
import { defineLink } from "@medusajs/utils"
3+
import BrandModule from "../modules/brand"
4+
5+
const link =
6+
process.env.ENABLE_INDEX_MODULE === "true"
7+
? defineLink(
8+
{
9+
linkable: ProductModule.linkable.product.id,
10+
filterable: ["description", "material"],
11+
isList: true,
12+
},
13+
{
14+
linkable: BrandModule.linkable.brand.id,
15+
filterable: ["id", "name"],
16+
isList: false,
17+
}
18+
)
19+
: {}
20+
21+
export default link
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { Module } from "@medusajs/utils"
2+
import { BrandModuleService } from "./service"
3+
4+
export const BRAND_MODULE = "brand"
5+
6+
export default Module(BRAND_MODULE, {
7+
service: BrandModuleService,
8+
})
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Migration } from "@mikro-orm/migrations"
2+
3+
export class Migration20250805184935 extends Migration {
4+
override async up(): Promise<void> {
5+
this.addSql(
6+
`create table if not exists "brand" ("id" text not null, "name" text not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "brand_pkey" primary key ("id"));`
7+
)
8+
this.addSql(
9+
`CREATE INDEX IF NOT EXISTS "IDX_brand_deleted_at" ON "brand" (deleted_at) WHERE deleted_at IS NULL;`
10+
)
11+
}
12+
13+
override async down(): Promise<void> {
14+
this.addSql(`drop table if exists "brand" cascade;`)
15+
}
16+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { model } from "@medusajs/utils"
2+
3+
export const Brand = model.define("brand", {
4+
id: model.id({ prefix: "brand" }).primaryKey(),
5+
name: model.text(),
6+
})
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { MedusaService } from "@medusajs/utils"
2+
import { Brand } from "./models/brand"
3+
4+
export class BrandModuleService extends MedusaService({
5+
Brand,
6+
}) {}

packages/modules/index/src/utils/build-config.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1206,7 +1206,12 @@ function buildSchemaFromFilterableLinks(
12061206
})
12071207
.join("\n")
12081208

1209-
return `extend type ${entity} ${events} {
1209+
return `
1210+
type ${entity} ${events} {
1211+
id: ID!
1212+
}
1213+
1214+
extend type ${entity} {
12101215
${fieldDefinitions}
12111216
}`
12121217
})

0 commit comments

Comments
 (0)