No description
Find a file
2017-11-12 18:11:55 +01:00
cmd moved filter logic into query 2017-11-12 14:33:39 +01:00
.gitignore fixed issues found by go-fuzz 2017-11-12 03:09:32 +01:00
cache.go added query cache 2017-11-12 16:53:09 +01:00
errors.go better errors 2017-11-12 18:11:55 +01:00
filter.go better errors 2017-11-12 18:11:55 +01:00
filter_test.go added query cache 2017-11-12 16:53:09 +01:00
helper.go better errors 2017-11-12 18:11:55 +01:00
LICENSE initial commit 2017-07-09 01:05:58 +02:00
README.md moved filter logic into query 2017-11-12 14:33:39 +01:00

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 (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