Skip to content

Commit ccd2001

Browse files
Implement $nin
1 parent bbadf91 commit ccd2001

File tree

3 files changed

+25
-6
lines changed

3 files changed

+25
-6
lines changed

filter/converter.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,16 @@ func (c *Converter) convertFilter(filter map[string]any, paramIndex int) (string
140140
return "", nil, fmt.Errorf("$or as scalar operator not supported")
141141
case "$and":
142142
return "", nil, fmt.Errorf("$and as scalar operator not supported")
143-
case "$in":
143+
case "$in", "$nin":
144144
if !isScalarSlice(v[operator]) {
145145
return "", nil, fmt.Errorf("invalid value for $in operator (must array of primatives): %v", v[operator])
146146
}
147-
inner = append(inner, fmt.Sprintf("(%s = ANY($%d))", c.columnName(key), paramIndex))
147+
op := ""
148+
if operator == "$nin" {
149+
op = "NOT "
150+
}
151+
// `column != ANY(...)` does not work, so we need to do `NOT column = ANY(...)` instead.
152+
inner = append(inner, fmt.Sprintf("(%s%s = ANY($%d))", op, c.columnName(key), paramIndex))
148153
paramIndex++
149154
if c.arrayDriver != nil {
150155
v[operator] = c.arrayDriver(v[operator])

filter/converter_test.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,31 +74,39 @@ func TestConverter_Convert(t *testing.T) {
7474
nil,
7575
},
7676
{
77-
"in-array operator simple",
77+
"simple $in",
7878
nil,
7979
`{"status": {"$in": ["NEW", "OPEN"]}}`,
8080
`("status" = ANY($1))`,
8181
[]any{[]any{"NEW", "OPEN"}},
8282
nil,
8383
},
8484
{
85-
"in-array operator invalid value",
85+
"simple $nin",
86+
nil,
87+
`{"status": {"$nin": ["NEW", "OPEN"]}}`,
88+
`(NOT "status" = ANY($1))`,
89+
[]any{[]any{"NEW", "OPEN"}},
90+
nil,
91+
},
92+
{
93+
"$in invalid value",
8694
nil,
8795
`{"status": {"$in": [{"hacker": 1}, "OPEN"]}}`,
8896
``,
8997
nil,
9098
fmt.Errorf("invalid value for $in operator (must array of primatives): [map[hacker:1] OPEN]"),
9199
},
92100
{
93-
"in-array operator scalar value",
101+
"$in scalar value",
94102
nil,
95103
`{"status": {"$in": "text"}}`,
96104
``,
97105
nil,
98106
fmt.Errorf("invalid value for $in operator (must array of primatives): text"),
99107
},
100108
{
101-
"in-array operator with null value",
109+
"$in with null value",
102110
nil,
103111
`{"status": {"$in": ["guest", null]}}`,
104112
`("status" = ANY($1))`,

integration/postgres_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,12 @@ func TestIntegration_BasicOperators(t *testing.T) {
297297
[]int{},
298298
nil,
299299
},
300+
{
301+
"$nin",
302+
`{"level": {"$nin": [20, 30, 40]}}`,
303+
[]int{1, 5, 6, 7, 8, 9, 10},
304+
nil,
305+
},
300306
}
301307

302308
for _, tt := range tests {

0 commit comments

Comments
 (0)