# filter - a simple struct field filter and sorter for go ## Query Syntax ### Matching Explicit match: `:` Wildcard match (use ** to match the '*' character): ``` :* :* :** ``` Nested structs: `.:` Multiple matches (seperated by a single whitespace): ``` : :* ``` Bool does not support the wildcard operator, only the literal strings `true` and `false`. ### Sorting The sort statement consists of the literal string `sort`, the field name (nesting like above is supported) and the literal strings `asc` or `desc`. ``` sort::asc sort::desc sort:.:desc ``` ### Struct fields Supported struct field values are: * `int`, `int8`, `int16`, `int32`, `int64` * `float32`, `float64` * `string` * `bool` For nested structs: * `struct` ### Filter logic Supported logical matching: * `AND` - all statements have to match (if no logic is provided, this is the default) * `OR` - only one statement has to match * `NOT` - none of the statements have to match ## Examples ``` // Example data structure type Example struct { String string Int int Bool bool Struct Struct1 } type Struct1 struct { String string Struct Struct2 } type Struct2 struct { Int int } // Filter implements the filter.Filter interface type Filter []Example func (v Filter) Len() int { return len(v) } func (v Filter) Index(i int) interface{} { return v[i] } func (v *Filter) Remove(i, j int) { *v = append((*v)[:i], (*v)[j:]...) } // Example data var data = Filter{ {"str1", 42, true, Struct1{"s1", Struct2{1}}}, {"2str", 42, true, Struct1{"s2", Struct2{2}}}, {"str3", 42, false, Struct1{"s3", Struct2{3}}}, } ``` ### Explicit match ``` filter.NewQuery("OR Bool:true").Filter(&data) data = [{str1 42 true {s1 {1}}} {str2 42 true {s2 {2}}}] ``` ### Wildcard match Wildcard operator: `*` To match the `'*'` character use: `**` ``` filter.NewQuery("OR String:s*").Filter(&data) data = [{str1 42 true {s1 {1}}} {str3 42 false {s3 {3}}}] ``` ### Nested struct match ``` filter.NewQuery("OR Struct.Struct.Int:3").Filter(&data) data = [{str3 42 false {s3 {3}}}] ``` ### Multiple matches ``` filter.NewQuery("Struct.String:*2 Bool:true").Filter(&data) data = [{2str 42 true {s2 {2}}}] ``` ### Sorting The `GenericFilter` does not support sorting. #### Sort ``` filter.NewQuery("sort:Bool:desc").Filter(&data) data = [{str1 42 false {s1 {1}}} {2str 42 true {s2 {2}}} {str3 42 true {s3 {3}}}] ``` #### Sort and Filter ``` filter.NewQuery("sort:Bool:desc String:str*").Filter(&data) data = [{str1 42 false {s1 {1}}} {str3 42 true {s3 {3}}}] ``` ## Benchmarks ``` go test -bench . BenchmarkNewQuerySimple-4 2000000 974 ns/op 272 B/op 8 allocs/op BenchmarkNewQueryComplex-4 500000 2779 ns/op 848 B/op 20 allocs/op BenchmarkNewQueryComplexOr-4 500000 2677 ns/op 832 B/op 20 allocs/op BenchmarkNewQuerySort-4 3000000 576 ns/op 160 B/op 4 allocs/op BenchmarkNewQuerySortSimple-4 1000000 1192 ns/op 304 B/op 9 allocs/op BenchmarkNewQuerySortComplex-4 500000 2598 ns/op 784 B/op 19 allocs/op BenchmarkNewQuerySortComplexOr-4 500000 2326 ns/op 768 B/op 19 allocs/op BenchmarkFilterSimple-4 1000000 2123 ns/op 432 B/op 12 allocs/op BenchmarkFilterComplex-4 200000 6840 ns/op 672 B/op 42 allocs/op BenchmarkFilterComplexOr-4 300000 5929 ns/op 744 B/op 30 allocs/op BenchmarkSort-4 200000 7859 ns/op 1864 B/op 51 allocs/op BenchmarkSortFilterSimple-4 200000 6294 ns/op 1432 B/op 39 allocs/op BenchmarkSortFilterComplex-4 200000 11990 ns/op 1672 B/op 69 allocs/op BenchmarkSortFilterComplexOr-4 200000 12138 ns/op 2176 B/op 69 allocs/op BenchmarkGenericFilterSimple-4 300000 5939 ns/op 1200 B/op 24 allocs/op BenchmarkGenericFilterComplex-4 100000 16638 ns/op 1680 B/op 84 allocs/op BenchmarkGenericFilterComplexOr-4 200000 11846 ns/op 2360 B/op 49 allocs/op ```