169 lines
4.5 KiB
Markdown
169 lines
4.5 KiB
Markdown
# filter - a simple struct field filter and sorter for go
|
|
|
|
## Query Syntax
|
|
|
|
### Matching
|
|
|
|
Explicit match: `<struct field>:<struct value>`
|
|
|
|
Wildcard match (use ** to match the '*' character):
|
|
|
|
```
|
|
<struct field>:*<right part of struct value>
|
|
<struct field>:<left part of struct value>*
|
|
<struct field>:*<middl of struct value>*
|
|
```
|
|
|
|
Nested structs: `<struct field>.<struct field>:<struct value>`
|
|
|
|
Multiple matches (seperated by a single whitespace):
|
|
|
|
```
|
|
<struct field>:<struct value> <struct field>:<struct value>*
|
|
```
|
|
|
|
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:<struct field>:asc
|
|
sort:<struct field>:desc
|
|
sort:<struct field>.<struct field>: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
|
|
* `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("Bool:true", filter.OR).Filter(&data)
|
|
|
|
data = [{str1 42 true {s1 {1}}} {str2 42 true {s2 {2}}}]
|
|
```
|
|
|
|
### Wildcard match
|
|
|
|
Wildcard operator: `*`
|
|
To match the `'*'` character use: `**`
|
|
|
|
```
|
|
filter.NewQuery("String:s*", filter.OR).Filter(&data)
|
|
|
|
data = [{str1 42 true {s1 {1}}} {str3 42 false {s3 {3}}}]
|
|
```
|
|
|
|
### Nested struct match
|
|
|
|
```
|
|
filter.NewQuery("Struct.Struct.Int:3", filter.OR).Filter(&data)
|
|
|
|
data = [{str3 42 false {s3 {3}}}]
|
|
```
|
|
|
|
### Multiple matches
|
|
|
|
```
|
|
filter.NewQuery("Struct.String:*2 Bool:true", filter.AND).Filter(&data)
|
|
|
|
data = [{2str 42 true {s2 {2}}}]
|
|
```
|
|
|
|
### Sorting
|
|
|
|
The `GenericFilter` does not support sorting.
|
|
|
|
#### Sort
|
|
|
|
```
|
|
filter.NewQuery("sort:Bool:desc", filter.AND).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.AND).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
|
|
```
|