Skip to content

Commit 8cf30f2

Browse files
Dragomir-Ivanovsmyrman
authored andcommitted
Fix filtering in schema.Array for scalar values
Filtering on `schema.Array` for a single array match on MongoDB can be done with query like `{arr: value}`, where it will return all documents whose `arr` field, contains the value (and may cointain other values as well). Relates to #5003f4f5, where support in `rest-layer-mem` was added.
1 parent 85bae90 commit 8cf30f2

File tree

3 files changed

+76
-12
lines changed

3 files changed

+76
-12
lines changed

rest/method_get_test.go

Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,73 @@ func TestGetListFilter(t *testing.T) {
345345
}
346346

347347
func TestGetListArray(t *testing.T) {
348+
sharedInit := func() *requestTestVars {
349+
s := mem.NewHandler()
350+
s.Insert(context.TODO(), []*resource.Item{
351+
{ID: "1", Payload: map[string]interface{}{"id": 1,
352+
"foo": []interface{}{"bar", "baz"}},
353+
},
354+
{ID: "2", Payload: map[string]interface{}{"id": 2,
355+
"foo": []interface{}{"bar"}},
356+
},
357+
{ID: "3", Payload: map[string]interface{}{"id": 3,
358+
"foo": []interface{}{"baz"}},
359+
},
360+
})
361+
362+
idx := resource.NewIndex()
363+
idx.Bind("foo", schema.Schema{
364+
Fields: schema.Fields{
365+
"foo": {
366+
Filterable: true,
367+
Validator: &schema.Array{
368+
Values: schema.Field{
369+
Validator: &schema.String{},
370+
},
371+
},
372+
},
373+
},
374+
}, s, resource.DefaultConf)
375+
376+
return &requestTestVars{
377+
Index: idx,
378+
Storers: map[string]resource.Storer{"foo": s},
379+
}
380+
}
381+
382+
tests := map[string]requestTest{
383+
`filter/array:foo:not-found`: {
384+
Init: sharedInit,
385+
NewRequest: func() (*http.Request, error) {
386+
return http.NewRequest("GET", `/foo?filter={foo:"mar"}`, nil)
387+
},
388+
ResponseCode: http.StatusOK,
389+
ResponseBody: `[]`,
390+
},
391+
`filter/array:foo:try-object`: {
392+
Init: sharedInit,
393+
NewRequest: func() (*http.Request, error) {
394+
return http.NewRequest("GET", `/foo?filter={foo:{bar:"mar"}}`, nil)
395+
},
396+
ResponseCode: 422,
397+
ResponseBody: `{"code":422,"issues":{"filter":["foo: invalid query expression: invalid value at #1: not a string"]},"message":"URL parameters contain error(s)"}`,
398+
},
399+
`filter/array:foo:find`: {
400+
Init: sharedInit,
401+
NewRequest: func() (*http.Request, error) {
402+
return http.NewRequest("GET", `/foo?filter={foo:"bar"}`, nil)
403+
},
404+
ResponseCode: http.StatusOK,
405+
ResponseBody: `[{"foo":["bar","baz"],"id":1},{"foo":["bar"],"id":2}]`,
406+
},
407+
}
408+
for n, tc := range tests {
409+
tc := tc // capture range variable
410+
t.Run(n, tc.Test)
411+
}
412+
}
413+
414+
func TestGetListArrayOfObjects(t *testing.T) {
348415
sharedInit := func() *requestTestVars {
349416
s := mem.NewHandler()
350417
s.Insert(context.TODO(), []*resource.Item{
@@ -573,14 +640,6 @@ func TestGetListArray(t *testing.T) {
573640
{"id":2,"foo":[{"a":"bar","b":20}]}
574641
]`,
575642
},
576-
`filter/array:foo:not-an-array`: {
577-
Init: sharedInit,
578-
NewRequest: func() (*http.Request, error) {
579-
return http.NewRequest("GET", `/foo?filter={foo:"mar"}`, nil)
580-
},
581-
ResponseCode: http.StatusUnprocessableEntity,
582-
ResponseBody: `{"code":422,"issues":{"filter":["foo: invalid query expression: not an array"]},"message":"URL parameters contain error(s)"}`,
583-
},
584643
`filter/array:foo:invalid-elemMatch`: {
585644
Init: sharedInit,
586645
NewRequest: func() (*http.Request, error) {

schema/array.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,19 @@ func (v Array) validateValues(values []interface{}, query bool) ([]interface{},
5050

5151
// ValidateQuery implements FieldQueryValidator.
5252
func (v Array) ValidateQuery(value interface{}) (interface{}, error) {
53-
values, ok := value.([]interface{})
54-
if !ok {
55-
return nil, errors.New("not an array")
53+
values, isArray := value.([]interface{})
54+
if !isArray {
55+
values = append(values, value)
5656
}
57+
5758
arr, err := v.validateValues(values, true)
5859
if err != nil {
5960
return nil, err
6061
}
62+
63+
if !isArray {
64+
return arr[0], nil
65+
}
6166
return arr, nil
6267
}
6368

schema/array_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ func TestArrayQueryValidator(t *testing.T) {
119119
Name: `Values.Validator=&String{},ValidateQuery("value")`,
120120
Validator: &schema.Array{Values: schema.Field{Validator: &schema.String{}}},
121121
Input: "value",
122-
Error: "not an array",
122+
Expect: "value",
123123
},
124124
{
125125
Name: `MinLen=2,ValidateQuery([]interface{}{true,false})`,

0 commit comments

Comments
 (0)