Skip to content

Commit

Permalink
coalesce
Browse files Browse the repository at this point in the history
  • Loading branch information
carlos-r-l-rodrigues committed Jan 11, 2025
1 parent bc6c920 commit ab299f0
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ export const schema = `
}
type Price @Listeners(values: ["price.created", "price.updated", "price.deleted"]) {
amount: Int
amount: Float
}
`
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import {
ModuleRegistrationName,
Modules,
} from "@medusajs/framework/utils"
import { initDb, TestDatabaseUtils } from "@medusajs/test-utils"
import { EntityManager } from "@mikro-orm/postgresql"
import { IndexData, IndexRelation } from "@models"
import { asValue } from "awilix"
import { initDb, TestDatabaseUtils } from "@medusajs/test-utils"
import path from "path"
import { EventBusServiceMock } from "../__fixtures__"
import { dbName } from "../__fixtures__/medusa-config"
Expand Down Expand Up @@ -343,6 +343,116 @@ describe("IndexModuleService query", function () {
])
})

it("should query all products ordered by price", async () => {
const { data } = await module.query({
fields: ["product.*", "product.variants.*", "product.variants.prices.*"],
pagination: {
order: {
product: {
variants: {
prices: {
amount: "DESC",
},
},
},
},
},
})

expect(data).toEqual([
{
id: "prod_1",
variants: [
{
id: "var_1",
sku: "aaa test aaa",
prices: [
{
id: "money_amount_1",
amount: 100,
},
],
},
{
id: "var_2",
sku: "sku 123",
prices: [
{
id: "money_amount_2",
amount: 10,
},
],
},
],
},
{
id: "prod_2",
title: "Product 2 title",
deep: {
a: 1,
obj: {
b: 15,
},
},
variants: [],
},
])

const { data: dataAsc } = await module.query({
fields: ["product.*", "product.variants.*", "product.variants.prices.*"],
pagination: {
order: {
product: {
variants: {
prices: {
amount: "ASC",
},
},
},
},
},
})

expect(dataAsc).toEqual([
{
id: "prod_2",
title: "Product 2 title",
deep: {
a: 1,
obj: {
b: 15,
},
},
variants: [],
},
{
id: "prod_1",
variants: [
{
id: "var_2",
sku: "sku 123",
prices: [
{
id: "money_amount_2",
amount: 10,
},
],
},
{
id: "var_1",
sku: "aaa test aaa",
prices: [
{
id: "money_amount_1",
amount: 100,
},
],
},
],
},
])
})

it("should query products filtering by variant sku", async () => {
const { data } = await module.query({
fields: ["product.*", "product.variants.*", "product.variants.prices.*"],
Expand Down
39 changes: 29 additions & 10 deletions packages/modules/index/src/utils/query-builder.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Knex } from "@mikro-orm/knex"
import { IndexTypes } from "@medusajs/framework/types"
import { GraphQLUtils, isObject, isString } from "@medusajs/framework/utils"
import { Knex } from "@mikro-orm/knex"
import { OrderBy, QueryFormat, QueryOptions, Select } from "@types"
import { isObject, isString, GraphQLUtils } from "@medusajs/framework/utils"

export const OPERATOR_MAP = {
$eq: "=",
Expand Down Expand Up @@ -108,14 +108,34 @@ export class QueryBuilder {
"": "",
}

const defaultValues = {
Int: "0",
Float: "0",
Boolean: "false",
Date: "1970-01-01 00:00:00",
Time: "00:00:00",
"": "",
}

const fullPath = [path, ...field]
const prop = fullPath.pop()
const fieldPath = fullPath.join(".")
let graphqlType = this.getGraphQLType(fieldPath, prop)
const isList = graphqlType.endsWith("[]")
graphqlType = graphqlType.replace("[]", "")

return (graphqlToPostgresTypeMap[graphqlType] ?? "") + (isList ? "[]" : "")
const cast =
(graphqlToPostgresTypeMap[graphqlType] ?? "") + (isList ? "[]" : "")

function generateCoalesceExpression(field) {
const defaultValue = defaultValues[graphqlType]
return `COALESCE(${field}, '${defaultValue}')${cast}`
}

return {
cast,
coalesce: generateCoalesceExpression,
}
}

private parseWhere(
Expand Down Expand Up @@ -188,7 +208,7 @@ export class QueryBuilder {
field,
value[subKey]
)
const castType = this.getPostgresCastType(attr, field)
const castType = this.getPostgresCastType(attr, [field]).cast

const val = operator === "IN" ? subValue : [subValue]
if (operator === "=" && subValue === null) {
Expand Down Expand Up @@ -219,7 +239,7 @@ export class QueryBuilder {

value = this.transformValueToType(attr, field, value)
if (Array.isArray(value)) {
const castType = this.getPostgresCastType(attr, field)
const castType = this.getPostgresCastType(attr, field).cast
const inPlaceholders = value.map(() => "?").join(",")
builder.whereRaw(
`(${aliasMapping[attr]}.data${nested}->>?)${castType} IN (${inPlaceholders})`,
Expand All @@ -237,7 +257,7 @@ export class QueryBuilder {
)}'::jsonb`
)
} else {
const castType = this.getPostgresCastType(attr, field)
const castType = this.getPostgresCastType(attr, field).cast
builder.whereRaw(
`(${aliasMapping[attr]}.data${nested}->>?)${castType} ${operator} ?`,
[...field, value]
Expand Down Expand Up @@ -495,15 +515,14 @@ export class QueryBuilder {
for (const aliasPath in orderBy) {
const path = aliasPath.split(".")
const field = path.pop()

const pgType = this.getPostgresCastType(path, [field])

const attr = path.join(".")

const pgType = this.getPostgresCastType(attr, [field])
const alias = aliasMapping[attr]
const direction = orderBy[aliasPath]

queryBuilder.orderByRaw(
`${alias}.data->>'${field}'::${pgType} ${direction}`
pgType.coalesce(`${alias}.data->>'${field}'`) + " " + direction
)
}

Expand Down

0 comments on commit ab299f0

Please sign in to comment.