Skip to content

linka-cloud/protofilters

Repository files navigation

Proto Filters

Go Reference

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.

Overview

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;
  }
}

Usage

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")
	}
}

TODOs

  • support more languages