Skip to content

Commit

Permalink
feat: improve searching using contains operator for sets
Browse files Browse the repository at this point in the history
Fixes #667
  • Loading branch information
benhutchins committed Sep 14, 2023
1 parent f81ed8b commit 7ae830b
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 7 deletions.
4 changes: 2 additions & 2 deletions src/query/condition.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { type Table } from '../dyngoose'
import { type Filter } from './filters'
import { type ContainsType, type Filter } from './filters'
import { type MagicSearch } from './search'

export class Condition<T extends Table, Attr, AttributeValueType> {
Expand Down Expand Up @@ -123,7 +123,7 @@ export class Condition<T extends Table, Attr, AttributeValueType> {
*
* When using `.not().contains(value)` this checks for the absence of a subsequence, or absence of a value in a set.
*/
contains(value: AttributeValueType extends Array<infer E> ? E : AttributeValueType): MagicSearch<T> {
contains(value: ContainsType<AttributeValueType>): MagicSearch<T> {
if (this._not) {
this.filter = ['not contains', value as any]
} else {
Expand Down
8 changes: 6 additions & 2 deletions src/query/filters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import { type Table } from '../table'

export type AttributeNames<T extends Table> = Exclude<Exclude<keyof T, keyof Table>, () => any>

export type ContainsType<Type> = Type extends Array<infer E>
? E
: Type extends Set<infer E> ? E : Type

export type Filter<Type> =
['=', Type] |
['<>', Type] | // not equals
Expand All @@ -13,8 +17,8 @@ export type Filter<Type> =
['between', Type, Type] |
['includes', Type[]] |
['excludes', Type[]] |
['contains', Type] | // contains can be used on a list or a string attribute
['not contains', Type] | // not contains can be used on a list or a string attribute
['contains', ContainsType<Type>] | // contains can be used on a list, string, or set attributes
['not contains', ContainsType<Type>] | // not contains can be used on a list, string, or set attributes
['null'] |
['not null'] |
['exists'] |
Expand Down
19 changes: 16 additions & 3 deletions src/query/search.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { MagicSearch } from './search'

describe('Query/Search', () => {
before(async () => {
const sets = { testStringSet: new Set(['search']), testStringSetArray: ['search'] }
await TestableTable.documentClient.batchPut([
TestableTable.new({ id: 500, title: 'Table.search 0', lowercaseString: 'table search 0' }),
TestableTable.new({ id: 501, title: 'Table.search 1', lowercaseString: 'table search 1' }),
TestableTable.new({ id: 502, title: 'Table.search 2', lowercaseString: 'table search 2' }),
TestableTable.new({ id: 500, title: 'Table.search 0', lowercaseString: 'table search 0', ...sets }),
TestableTable.new({ id: 501, title: 'Table.search 1', lowercaseString: 'table search 1', ...sets }),
TestableTable.new({ id: 502, title: 'Table.search 2', lowercaseString: 'table search 2', ...sets }),
TestableTable.new({ id: 503, title: 'Table.search 3', lowercaseString: 'table search 3' }),
TestableTable.new({ id: 504, title: 'Table.search 4', lowercaseString: 'reject the search 4' }),
TestableTable.new({ id: 504, title: 'Table.search 5', lowercaseString: 'magic' }),
Expand Down Expand Up @@ -91,6 +92,18 @@ describe('Query/Search', () => {
expect(result.count).to.eq(3)
})

it('should support filtering on sets', async () => {
const search = new MagicSearch<TestableTable>(TestableTable)
.filter('testStringSet').contains('search')
.and()
.filter('testStringSetArray').contains('search')
const input = search.getInput()
expect(input.IndexName).to.be.a('undefined')
expect(input.FilterExpression).to.eq('contains(#a0, :v0) AND contains(#a1, :v0)')
const result = await search.exec()
expect(result.count).to.eq(3)
})

it('ConsistentRead defaults to false', async () => {
const search = new MagicSearch<TestableTable>(TestableTable)
const input = search.getInput()
Expand Down

0 comments on commit 7ae830b

Please sign in to comment.