Skip to content

Commit

Permalink
feat: add limit & offset to the catalog search pre-query (#356)
Browse files Browse the repository at this point in the history
  • Loading branch information
juanmahidalgo authored Oct 4, 2023
1 parent 2d90377 commit d668639
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 38 deletions.
6 changes: 1 addition & 5 deletions src/ports/catalog/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,7 @@ export function createCatalogComponent(options: {
if (filters.search) {
for (const schema of Object.values(reducedSchemas)) {
const filteredItemsById = await client.query<CollectionsItemDBResult>(
getItemIdsBySearchTextQuery(
schema,
filters.search,
filters.category
)
getItemIdsBySearchTextQuery(schema, filters)
)
filters.ids = [
...(filters.ids ?? []),
Expand Down
9 changes: 5 additions & 4 deletions src/ports/catalog/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -456,9 +456,9 @@ export const getCollectionsItemsCatalogQuery = (

export const getItemIdsBySearchTextQuery = (
schemaVersion: string,
search: CatalogQueryFilters['search'],
category: CatalogQueryFilters['category']
filters: CatalogQueryFilters
) => {
const { category, search, limit, offset } = filters
const query = SQL`SELECT items.id`
.append(` FROM `)
.append(schemaVersion)
Expand All @@ -469,9 +469,10 @@ export const getItemIdsBySearchTextQuery = (
.append(getSearchWhere({ search, category }))
.append(
category
? SQL` ORDER BY GREATEST(similarity(word, ${search})) DESC;`
: SQL` ORDER BY GREATEST(similarity(word_wearable, ${search}), similarity(word_emote, ${search})) DESC;`
? SQL` ORDER BY GREATEST(similarity(word, ${search})) DESC`
: SQL` ORDER BY GREATEST(similarity(word_wearable, ${search}), similarity(word_emote, ${search})) DESC`
)
.append(SQL` LIMIT ${limit} OFFSET ${offset};`)

return query
}
55 changes: 40 additions & 15 deletions src/tests/ports/catalog-queries.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -503,25 +503,36 @@ test('catalog utils', () => {
let search: string
let schema: string
let category: NFTCategory
let limit: number
let offset: number
beforeEach(() => {
schema = 'aSchema'
search = 'a search string'
limit = 10
offset = 0
})

describe('and there is no category', () => {
it('should both JOINs with metadata_wearable and metadata_emote and trigram matching operator', () => {
const query = getItemIdsBySearchTextQuery(schema, search, category)
const query = getItemIdsBySearchTextQuery(schema, {
search,
category,
limit,
offset,
})
expect(query.text).toContain(
`LEFT JOIN LATERAL unnest(string_to_array(metadata_wearable.name, ' ')) AS word_wearable ON TRUE `
)
expect(query.text).toContain(
`LEFT JOIN LATERAL unnest(string_to_array(metadata_emote.name, ' ')) AS word_emote ON TRUE `
)
expect(query.text).toContain(
`word_wearable % $1 OR word_emote % $2 `
)
expect(query.text).toContain(`word_wearable % $1 OR word_emote % $2 `)
// it appears four times `JOIN LATERAL unnest(string_to_array(metadata_emote.name, ' ')) AS word ON TRUE WHERE word % $1 ORDER BY GREATEST(similarity(word, $2))`
expect(query.values).toStrictEqual(Array(4).fill(search))
expect(query.values).toStrictEqual([
...Array(4).fill(search),
limit,
offset,
])
})
})

Expand All @@ -530,15 +541,22 @@ test('catalog utils', () => {
category = NFTCategory.WEARABLE
})
it('should add JOIN with the metadata_wearable and trigram matching operator', () => {
const query = getItemIdsBySearchTextQuery(schema, search, category)
const query = getItemIdsBySearchTextQuery(schema, {
search,
category,
limit,
offset,
})
expect(query.text).toContain(
`JOIN LATERAL unnest(string_to_array(metadata_wearable.name, ' ')) AS word ON TRUE `
)
expect(query.text).toContain(
`word % $1 `
)
expect(query.text).toContain(`word % $1 `)
// it appears twice `JOIN LATERAL unnest(string_to_array(metadata_wearable.name, ' ')) AS word ON TRUE WHERE word % $1 ORDER BY GREATEST(similarity(word, $2))`
expect(query.values).toStrictEqual(Array(2).fill(search))
expect(query.values).toStrictEqual([
...Array(2).fill(search),
limit,
offset,
])
})
})

Expand All @@ -547,15 +565,22 @@ test('catalog utils', () => {
category = NFTCategory.EMOTE
})
it('should add JOIN with the metadata_emote', () => {
const query = getItemIdsBySearchTextQuery(schema, search, category)
const query = getItemIdsBySearchTextQuery(schema, {
search,
category,
limit,
offset,
})
expect(query.text).toContain(
`JOIN LATERAL unnest(string_to_array(metadata_emote.name, ' ')) AS word ON TRUE `
)
expect(query.text).toContain(
`word % $1 `
)
expect(query.text).toContain(`word % $1 `)
// it appears twice `JOIN LATERAL unnest(string_to_array(metadata_emote.name, ' ')) AS word ON TRUE WHERE word % $1 ORDER BY GREATEST(similarity(word, $2))`
expect(query.values).toStrictEqual(Array(2).fill(search))
expect(query.values).toStrictEqual([
...Array(2).fill(search),
limit,
offset,
])
})
})
})
Expand Down
31 changes: 17 additions & 14 deletions src/tests/ports/catalog.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,16 +285,20 @@ test('catalog component', function () {
let pickStats: PickStats
let network = Network.ETHEREUM
let filters: CatalogFilters
let limit: number, offset: number
let latestSchema = 'sgd1234'
let search: string

beforeEach(() => {
search = 'aSearchTerm'
limit = 10
offset = 0
filters = {
network,
search,
limit,
offset,
}

latestSubgraphSchemaResponse = {
rows: [
{
Expand Down Expand Up @@ -326,16 +330,17 @@ test('catalog component', function () {
)
const itemIdsBySearchTextQuery = getItemIdsBySearchTextQuery(
latestSchema,
filters.search,
filters.category
filters
)
expect(dbClientQueryMock.mock.calls[1][0]).toEqual(
itemIdsBySearchTextQuery
)
// It's repeated 4 times due to this WHERE statement: `WHERE word_wearable % $1 OR word_emote % $2 ORDER BY GREATEST(similarity(word_wearable, $3), similarity(word_emote, $4)) DESC;`
expect(dbClientQueryMock.mock.calls[1][0].values).toEqual(
Array(4).fill(search)
)
expect(dbClientQueryMock.mock.calls[1][0].values).toEqual([
...Array(4).fill(search),
limit,
offset,
])
})
})

Expand Down Expand Up @@ -379,16 +384,14 @@ test('catalog component', function () {
)
)
expect(dbClientQueryMock.mock.calls[1][0]).toEqual(
getItemIdsBySearchTextQuery(
latestSchema,
filters.search,
filters.category
)
getItemIdsBySearchTextQuery(latestSchema, filters)
)
// It's repeated 4 times due to this WHERE statement: `WHERE word_wearable % $1 OR word_emote % $2 ORDER BY GREATEST(similarity(word_wearable, $3), similarity(word_emote, $4)) DESC;`
expect(dbClientQueryMock.mock.calls[1][0].values).toEqual(
Array(4).fill(search)
)
expect(dbClientQueryMock.mock.calls[1][0].values).toEqual([
...Array(4).fill(search),
limit,
offset,
])
const mainCatalogQuery = getCatalogQuery(
{ [network]: latestSchema },
{ ...filters, ids: [mockedDBItemResponse.id] } // the main query should have the ids returned by the search query
Expand Down

0 comments on commit d668639

Please sign in to comment.