Proto filters provides a simple way to filter protobuf message based on field filter conditions.
Project status: alpha
Not all planned features are completed. The API, spec, status and other user facing objects are subject to change. We do not support backward-compatibility for the alpha releases.
The main filter construct is the Expression:
// Expression represent a complete condition
// fields are evaluated as the following expression:
// condition && and_exprs || or_exprs
message Expression {
FieldFilter condition = 1;
repeated Expression and_exprs = 2;
repeated Expression or_exprs = 3;
}
The two message filtering types available follow the same pattern as google.protobuf.FieldMask
:
message FieldsFilter {
// filters is a map of <field path, Filter>
map<string, Filter> filters = 1;
}
message FieldFilter {
string field = 1;
Filter filter = 2;
}
The message's Field is selected by its path and compared against the provided typed filter:
message Filter {
oneof match {
StringFilter string = 1;
NumberFilter number = 2;
BoolFilter bool = 3;
NullFilter null = 4;
TimeFilter time = 5;
DurationFilter duration = 6;
}
// not negates the match result
bool not = 7;
}
The typed filters are the following:
message StringFilter {
message In {
repeated string values = 1;
}
oneof condition {
string equals = 1;
string regex = 2;
In in = 3;
}
bool case_insensitive = 4;
}
message NumberFilter {
message In {
repeated double values = 1;
}
oneof condition {
double equals = 1;
double sup = 2;
double inf = 3;
In in = 4;
}
}
message NullFilter {}
message BoolFilter {
bool equals = 1;
}
message TimeFilter {
oneof condition {
google.protobuf.Timestamp equals = 1;
google.protobuf.Timestamp before = 2;
google.protobuf.Timestamp after = 3;
}
}
message DurationFilter {
oneof condition {
google.protobuf.Duration equals = 1;
google.protobuf.Duration sup = 2;
google.protobuf.Duration inf = 3;
}
}
Download:
go get go.linka.cloud/protofilters
Basic example:
package main
import (
"log"
"google.golang.org/protobuf/types/known/wrapperspb"
"go.linka.cloud/protofilters"
"go.linka.cloud/protofilters/filters"
test "go.linka.cloud/protofilters/tests/pb"
)
func main() {
m := &test.Test{
BoolField: true,
BoolValueField: wrapperspb.Bool(false),
}
ok, err := protofilters.Match(m, filters.Where("bool_field").True())
if err != nil {
log.Fatalln(err)
}
if !ok {
log.Fatalln("should be true")
}
ok, err = protofilters.Match(m, filters.Where("bool_value_field").False())
if err != nil {
log.Fatalln(err)
}
if !ok {
log.Fatalln("should be true")
}
}
- support more languages