Skip to content

Commit

Permalink
add not() and or() to filter expression and add duplicate values support
Browse files Browse the repository at this point in the history
  • Loading branch information
dan-german committed Oct 5, 2023
1 parent e48b10d commit 6931fa3
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 7 deletions.
3 changes: 2 additions & 1 deletion src/expression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ export class ExpressionBuilder {
}

addValue(name: string, value: any, valueNameSuffix: string = ""): string {
const valueToken = `:${this.replaceAll(name, ".", "")}${valueNameSuffix}`;
let valueToken = `:${this.replaceAll(name, ".", "")}${valueNameSuffix}`;
if (this.values[valueToken]) valueToken += Object.keys(this.values).filter((k) => k.startsWith(valueToken)).length + 1;
this.values[valueToken] = value;
return valueToken;
}
Expand Down
5 changes: 5 additions & 0 deletions src/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ export abstract class Search extends Read {
filterBetween(key: string, value1: any, value2: any) { this.filterExpression.between(key, value1, value2); return this; }
filterIn(key: string, values: any[]) { this.filterExpression.in(key, values); return this; }

/** applies the NOT logical evaluation operator to the next filter statement */
not() { this.filterExpression.not(); return this; }
/** applies the OR logical evaluation operator to the next filter statement */
or() { this.filterExpression.or(); return this; }

build() {
const base: any = super.build();

Expand Down
24 changes: 18 additions & 6 deletions test/query.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,21 +89,27 @@ describe('query', () => {

query.key('PK', '=', 'id').key('SK', '<', -904)

query.filterBeginsWith('name', 'zzzzzzz').filterBetween('age', 0, 100)
query.filterBeginsWith('name', 'zzzzzzz')
query.filterBeginsWith('name', 'xxxxxx')
query.filterBeginsWith('name', 'aaaaaa').filterBetween('age', 0, 100)
query.filterContains('silhouette', 'friendofmine').filterExists('meeee')
query.filterIn('aaaaahhh', ['a', 'b', 'c']).filterNotExists('aaaaahhhhhhhhh')
query.not().filterIn('vroomvroom', ['bus', 'car', 'train'])
query.filterType('aaaaaaaahhhhhhhhhhhh', 'Null')

expect(query.build()).toEqual({
TableName: 'momentdivine',
FilterExpression:
'begins_with(#name, :nameBeginsWithConditionValue) '
+ 'AND begins_with(#name, :nameBeginsWithConditionValue2) '
+ 'AND begins_with(#name, :nameBeginsWithConditionValue3) '
+ 'AND #age BETWEEN :ageLower '
+ 'AND :ageUpper '
+ 'AND contains(#silhouette, :silhouetteContainsConditionValue) '
+ 'AND attribute_exists(#meeee) '
+ 'AND #aaaaahhh IN (:aaaaahhhInConditionValue0, :aaaaahhhInConditionValue1, :aaaaahhhInConditionValue2) '
+ 'AND attribute_not_exists(#aaaaahhhhhhhhh) '
+ 'AND NOT #vroomvroom IN (:vroomvroomInConditionValue0, :vroomvroomInConditionValue1, :vroomvroomInConditionValue2) '
+ 'AND attribute_type(#aaaaaaaahhhhhhhhhhhh, NULL)',
KeyConditionExpression: '#PK = :PKEqualsConditionValue AND #SK < :SKLessThanConditionValue',
ExpressionAttributeNames: {
Expand All @@ -115,16 +121,22 @@ describe('query', () => {
'#meeee': 'meeee',
'#aaaaahhh': 'aaaaahhh',
'#aaaaahhhhhhhhh': 'aaaaahhhhhhhhh',
'#aaaaaaaahhhhhhhhhhhh': 'aaaaaaaahhhhhhhhhhhh'
'#aaaaaaaahhhhhhhhhhhh': 'aaaaaaaahhhhhhhhhhhh',
'#vroomvroom': 'vroomvroom'
},
ExpressionAttributeValues: {
':nameBeginsWithConditionValue': 'zzzzzzz',
':nameBeginsWithConditionValue2': 'xxxxxx',
':nameBeginsWithConditionValue3': 'aaaaaa',
':ageLower': 0,
':ageUpper': 100,
':silhouetteContainsConditionValue': 'friendofmine',
':aaaaahhhInConditionValue0': 'a',
':aaaaahhhInConditionValue1': 'b',
':aaaaahhhInConditionValue2': 'c',
":vroomvroomInConditionValue0": "bus",
":vroomvroomInConditionValue1": "car",
":vroomvroomInConditionValue2": "train",
':PKEqualsConditionValue': 'id',
':SKLessThanConditionValue': -904
}
Expand All @@ -137,8 +149,8 @@ describe('query', () => {
query.filterSize('mzzz', '<>', 1)
query.filterSize('pageUP', '<', 2)
query.filterSize('ABCDEFG', '>', 3)
query.filterSize('pageDown', '<=', 4)
query.filterSize('WOWWW', '>=', 5)
query.or().filterSize('pageDown', '<=', 4)
query.not().filterSize('WOWWW', '>=', 5)

expect(query.build()).toEqual({
TableName: 'planteryduality',
Expand All @@ -147,8 +159,8 @@ describe('query', () => {
+ 'AND size(#mzzz) <> :mzzzSizeNotEqualsConditionValue '
+ 'AND size(#pageUP) < :pageUPSizeLessThanConditionValue '
+ 'AND size(#ABCDEFG) > :ABCDEFGSizeGreaterThanConditionValue '
+ 'AND size(#pageDown) <= :pageDownSizeLessThanOrEqualsConditionValue '
+ 'AND size(#WOWWW) >= :WOWWWSizeGreaterThanOrEqualsConditionValue',
+ 'OR size(#pageDown) <= :pageDownSizeLessThanOrEqualsConditionValue '
+ 'AND NOT size(#WOWWW) >= :WOWWWSizeGreaterThanOrEqualsConditionValue',
ExpressionAttributeNames: {
'#paaa': 'paaa',
'#mzzz': 'mzzz',
Expand Down
26 changes: 26 additions & 0 deletions test/update.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,11 @@ describe('update', () => {

update.condition('daze22.00', '=', true)
update.condition('car', '<>', 9)
update.condition('car', '<>', 10)
update.condition('71M3', '<=', 0)
update.condition('yes.h', '>=', -1)
update.condition('art', '<', 4)
update.condition('art', '<', 8)
update.condition('race', '>', 2)

update.conditionExists('emily_')
Expand Down Expand Up @@ -142,9 +144,11 @@ describe('update', () => {
":thatList": "bla",
':daze2200EqualsConditionValue': true,
':carNotEqualsConditionValue': 9,
':carNotEqualsConditionValue2': 10,
':71M3LessThanOrEqualsConditionValue': 0,
':yeshGreaterThanOrEqualsConditionValue': -1,
':artLessThanConditionValue': 4,
':artLessThanConditionValue2': 8,
':raceGreaterThanConditionValue': 2,
':iBeginsWithConditionValue': 'blocks',
':thisContainsConditionValue': 'that',
Expand All @@ -160,9 +164,11 @@ describe('update', () => {
ConditionExpression:
'#daze22.#00 = :daze2200EqualsConditionValue'
+ ' AND #car <> :carNotEqualsConditionValue'
+ ' AND #car <> :carNotEqualsConditionValue2'
+ ' AND #71M3 <= :71M3LessThanOrEqualsConditionValue'
+ ' AND #yes.#h >= :yeshGreaterThanOrEqualsConditionValue'
+ ' AND #art < :artLessThanConditionValue'
+ ' AND #art < :artLessThanConditionValue2'
+ ' AND #race > :raceGreaterThanConditionValue'
+ ' AND attribute_exists(#emily_)'
+ ' AND attribute_not_exists(#PT)'
Expand Down Expand Up @@ -218,4 +224,24 @@ describe('update', () => {
expect(update1.build()).toStrictEqual(expected1)
expect(update2.build()).toStrictEqual(expected2)
})

it('build with condition duplicates', () => {
const updateWithDuplicates = new Update('table1850', { PK: 'duplicates' })
updateWithDuplicates.condition('a', '=', 1)
updateWithDuplicates.condition('a', '=', 2)
updateWithDuplicates.condition('a', '=', 3)

expect(updateWithDuplicates.build()).toStrictEqual({
TableName: 'table1850',
Key: { PK: 'duplicates' },
UpdateExpression: '',
ExpressionAttributeNames: { '#a': 'a' },
ExpressionAttributeValues: {
':aEqualsConditionValue': 1,
':aEqualsConditionValue2': 2,
':aEqualsConditionValue3': 3,
},
ConditionExpression: "#a = :aEqualsConditionValue AND #a = :aEqualsConditionValue2 AND #a = :aEqualsConditionValue3"
})
})
})

0 comments on commit 6931fa3

Please sign in to comment.