/
filter.go
102 lines (91 loc) · 1.92 KB
/
filter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package facet
import (
"encoding/json"
"strings"
"github.com/RoaringBitmap/roaring"
"github.com/spf13/cast"
"github.com/spf13/viper"
)
func Filter(bits *roaring.Bitmap, fields []*Facet, filters []any) (*roaring.Bitmap, error) {
var (
and []*roaring.Bitmap
or []*roaring.Bitmap
not []*roaring.Bitmap
)
for _, field := range fields {
name := field.Attribute
for _, fs := range filters {
switch vals := fs.(type) {
case string:
vals, ok := strings.CutPrefix(vals, name+":")
if ok {
vals, n := strings.CutPrefix(vals, "-")
f := field.Filter(vals)
if n {
not = append(not, f)
} else {
and = append(and, f)
}
}
case []any:
os := cast.ToStringSlice(vals)
for _, o := range os {
o, ok := strings.CutPrefix(o, name+":")
if ok {
o, n := strings.CutPrefix(o, "-")
f := field.Filter(o)
if n {
xo := roaring.AndNot(bits, f)
or = append(or, xo)
} else {
or = append(or, f)
}
}
}
}
}
}
for _, n := range not {
bits.AndNot(n)
}
if len(and) > 0 {
arb := roaring.ParAnd(viper.GetInt("workers"), and...)
bits.And(arb)
}
if len(or) > 0 {
orb := roaring.ParOr(viper.GetInt("workers"), or...)
bits.And(orb)
}
return bits, nil
}
// FilteredItems returns the subset of data.
func FilteredItems(data []map[string]any, ids []any) []map[string]any {
if len(ids) == 0 {
return data
}
items := make([]map[string]any, len(ids))
for item, _ := range data {
for i, id := range ids {
if cast.ToInt(id) == item {
items[i] = data[item]
}
}
}
return items
}
func unmarshalFilter(dec string) ([]any, error) {
var f []any
err := json.Unmarshal([]byte(dec), &f)
if err != nil {
return nil, err
}
return f, nil
}
func bitsToIntSlice(bitmap *roaring.Bitmap) []int {
bits := bitmap.ToArray()
ids := make([]int, len(bits))
for i, b := range bits {
ids[i] = int(b)
}
return ids
}