feat(index): add filterable fields to link definition (#11898)

* feat(index): add filterable fields to link definition

* rm comment

* break recursion

* validate read only links

* validate filterable

* gql schema array

* link parents

* isInverse

* push id when not present

* Fix ciruclar relationships and add tests to ensure proper behaviour (part 1)

* log and fallback to entity.alias

* cleanup and fixes

* cleanup and fixes

* cleanup and fixes

* fix get attributes

* gql type

* unit test

* array inference

* rm only

* package.json

* pacvkage.json

* fix link retrieval on duplicated entity type and aliases + tests

* link parents as array

* Match only parent entity

* rm comment

* remove hard coded schema

* extend types

* unit test

* test

* types

* pagination type

* type

* fix integration tests

* Improve performance of in selection

* use @@ to filter property

* escape jsonPath

* add Event Bus by default

* changeset

* rm postgres analyze

* estimate count

* new query

* parent aliases

* inner query w/ filter and sort relations

* address comments

---------

Co-authored-by: adrien2p <adrien.deperetti@gmail.com>
Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
Carlos R. L. Rodrigues
2025-04-29 07:10:31 -03:00
committed by GitHub
parent 8a3f639f01
commit b868a4ef4d
37 changed files with 3285 additions and 755 deletions
@@ -414,7 +414,6 @@ describe("IndexModuleService query", function () {
},
})
// NULLS LAST (DESC = first)
expect(data).toEqual([
{
id: "prod_2",
@@ -526,7 +525,7 @@ describe("IndexModuleService query", function () {
})
expect(metadata).toEqual({
count: 1,
estimate_count: expect.any(Number),
skip: 0,
take: 100,
})
@@ -575,7 +574,7 @@ describe("IndexModuleService query", function () {
})
expect(metadata).toEqual({
count: 1,
estimate_count: expect.any(Number),
skip: 0,
take: 100,
})
@@ -631,6 +630,86 @@ describe("IndexModuleService query", function () {
])
})
it("should filter using IN operator with array of strings", async () => {
const { data } = await module.query({
fields: ["product.id", "product.variants.*"],
filters: {
product: {
variants: {
sku: { $in: ["sku 123", "aaa test aaa", "does-not-exist"] },
},
},
},
pagination: {
order: {
product: {
variants: {
prices: {
amount: "DESC",
},
},
},
},
},
})
expect(data).toEqual([
{
id: "prod_1",
variants: [
{
id: "var_1",
sku: "aaa test aaa",
},
{
id: "var_2",
sku: "sku 123",
},
],
},
])
})
it("should filter using IN operator with array of strings", async () => {
const { data } = await module.query({
fields: ["product.id", "product.variants.*"],
filters: {
product: {
variants: {
sku: { $in: ["sku 123", "aaa test aaa", "does-not-exist"] },
},
},
},
pagination: {
order: {
product: {
variants: {
prices: {
amount: "DESC",
},
},
},
},
},
})
expect(data).toEqual([
{
id: "prod_1",
variants: [
{
id: "var_1",
sku: "aaa test aaa",
},
{
id: "var_2",
sku: "sku 123",
},
],
},
])
})
it("should query products filtering by price and returning the complete entity", async () => {
const { data, metadata } = await module.query({
fields: ["product.*", "product.variants.*", "product.variants.prices.*"],
@@ -651,7 +730,7 @@ describe("IndexModuleService query", function () {
})
expect(metadata).toEqual({
count: 1,
estimate_count: expect.any(Number),
skip: 0,
take: 100,
})
@@ -736,11 +815,16 @@ describe("IndexModuleService query", function () {
pagination: {
take: 1,
skip: 1,
order: {
product: {
id: "ASC",
},
},
},
})
expect(metadata).toEqual({
count: 2,
estimate_count: expect.any(Number),
skip: 1,
take: 1,
})
@@ -759,77 +843,6 @@ describe("IndexModuleService query", function () {
])
})
it("should handle null values on where clause", async () => {
const { data: data_, metadata } = await module.query({
fields: ["product.*", "product.variants.*", "product.variants.prices.*"],
filters: {
product: {
variants: {
sku: null,
},
},
},
pagination: {
take: 100,
skip: 0,
},
})
expect(metadata).toEqual({
count: 1,
skip: 0,
take: 100,
})
expect(data_).toEqual([
{
id: "prod_2",
deep: { a: 1, obj: { b: 15 } },
title: "Product 2 title",
variants: [],
},
])
const { data, metadata: metadata2 } = await module.query({
fields: ["product.*", "product.variants.*", "product.variants.prices.*"],
filters: {
product: {
variants: {
sku: { $ne: null },
},
},
},
pagination: {
take: 100,
skip: 0,
},
})
expect(metadata2).toEqual({
count: 1,
skip: 0,
take: 100,
})
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 }],
},
],
},
])
})
it("should query products filtering by deep nested levels", async () => {
const { data, metadata } = await module.query({
fields: ["product.*"],
@@ -849,7 +862,7 @@ describe("IndexModuleService query", function () {
})
expect(metadata).toEqual({
count: 1,
estimate_count: expect.any(Number),
skip: 0,
take: 1,
})
@@ -866,4 +879,52 @@ describe("IndexModuleService query", function () {
},
])
})
it("should query products filtering by prices bigger than 20", async () => {
const { data, metadata } = await module.query({
fields: ["product.*", "product.variants.*", "product.variants.prices.*"],
filters: {
product: {
variants: {
prices: {
amount: { $gt: 20 },
},
},
},
},
pagination: {
take: 100,
skip: 0,
order: {
product: {
created_at: "ASC",
},
},
},
})
expect(metadata).toEqual({
estimate_count: expect.any(Number),
skip: 0,
take: 100,
})
expect(data).toEqual([
{
id: "prod_1",
variants: [
{
id: "var_1",
sku: "aaa test aaa",
prices: [
{
id: "money_amount_1",
amount: 100,
},
],
},
],
},
])
})
})