querybuilder

package
v0.0.0-...-cb472e6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 27, 2021 License: MIT Imports: 10 Imported by: 0

README

What is it

一个用于前端/API的查询参数解析mongodb过滤条件的后端模块, 支持类 jQuery-QueryBuilder 形式的输入参数.

与 jQuery-QueryBuilder 的区别

  • 不支持 type 字段,所有value字段均解析成基本字段类型
  • 为支持基于时间类型的对比,扩展除了相应的操作符
    • OperatorDatetimeLess ("datetime_less")
    • OperatorDatetimeLessOrEqual ("datetime_less_or_equal")
    • OperatorDatetimeGreater ("datetime_greater")
    • OperatorDatetimeGreaterOrEqual ("datetime_greater_or_equal")
  • 不支持 betweennot_between 运算符, 这类运算符可基于基本比较运算符组合实现

How it implemented

Rule

过滤规则的接口

  • GetDeep 定义过滤规则的深度
  • Validate 校验过滤规则是否有效
  • ToMgo 转换成mongodb查询条件

AtomRule

原子过滤规则,任何过滤规则都直接是原子过滤规则, 或由多个原子过滤规则按逻辑与/或组合而成

AtomRule.Field 字段
AtomRule.Operator 字段
AtomRule.Value 字段

CombinedRule

组合过滤规则,组合的节点可以是原子过滤规则或组合过滤规则

RuleParser

过滤规则解析方法,从map[string]interface{}数据中解析出一个过滤规则实例

Operator 详细说明

通用操作符

  • OperatorEqual ("equal")
    • 含义:相等比较
    • Value格式: 基本数据类型(数值/bool值/字符串)
  • OperatorNotEqual ("not_equal")
    • 含义:不等比较
    • Value格式: 基本数据类型(数值/bool值/字符串)

数组操作符

  • OperatorIn ("in")
    • 含义:匹配记录字段值是否在指定集合中
    • Value格式: 基本数据类型组成的数值,类型需要一致
  • OperatorNotIn ("not_in")
    • 含义:匹配记录字段值不在指定集合中
    • Value格式: 基本数据类型组成的数值,类型需要一致
  • OperatorIsEmpty ("is_empty")
    • 含义:匹配记录字段值为空数组
    • Value格式: 不接受参数
  • OperatorIsNotEmpty ("is_not_empty")
    • 含义:匹配记录字段值为非空数组
    • Value格式: 不接受参数

数字操作符

  • OperatorLess ("less")
    • 含义:匹配记录字段值 < {Value}
    • Value格式: 数值
  • OperatorLessOrEqual ("less_or_equal")
    • 含义:匹配记录字段值 <= {Value}
    • Value格式: 数值
  • OperatorGreater ("greater")
    • 含义:匹配记录字段值 > {Value}
    • Value格式: 数值
  • OperatorGreaterOrEqual ("greater_or_equal")
    • 含义:匹配记录字段值 >= {Value}
    • Value格式: 数值

时间操作符

目前仅支持 RFC3339 时间格式

  • OperatorDatetimeLess ("datetime_less")
    • 含义:匹配记录字段值表示的时间早于 < {Value}
    • Value格式: RFC3339 格式字符串
  • OperatorDatetimeLessOrEqual ("datetime_less_or_equal")
    • 含义:匹配记录字段值表示的时间不晚于 <= {Value}
    • Value格式: RFC3339 格式字符串
  • OperatorDatetimeGreater ("datetime_greater")
    • 含义:匹配记录字段值表示的时间晚于 < {Value}
    • Value格式: RFC3339 格式字符串
  • OperatorDatetimeGreaterOrEqual ("datetime_greater_or_equal")
    • 含义:匹配记录字段值表示的时间不早于 >= {Value}
    • Value格式: RFC3339 格式字符串

字符串操作符

  • OperatorBeginsWith ("begins_with")
    • 含义:匹配记录字段值是以{Value}开头的字符串
    • Value格式:非空字符串
  • OperatorNotBeginsWith ("not_begins_with")
    • 含义:匹配记录字段值不是以{Value}开头的字符串
    • Value格式:非空字符串
  • OperatorContains ("contains")
    • 含义:匹配记录字段值包含{Value}的字符串
    • Value格式:非空字符串
  • OperatorNotContains ("not_contains")
    • 含义:匹配记录字段值不包含{Value}的字符串
    • Value格式:非空字符串
  • OperatorsEndsWith ("ends_with")
    • 含义:匹配记录字段值是以{Value}结尾的字符串
    • Value格式:非空字符串
  • OperatorNotEndsWith ("not_ends_with")
    • 含义:匹配记录字段值不是以{Value}结尾的字符串
    • Value格式:非空字符串

空值操作符

  • OperatorIsNull ("is_null")
    • 含义:匹配记录字段值为 null
    • Value格式:不接受参数
  • OperatorIsNotNull ("is_not_null")
    • 含义:匹配记录字段值不为 null
    • Value格式:不接受参数

字段存在状态操作符

  • OperatorExist ("exist")
    • 含义:匹配记录包含字段 {Field}
    • Value格式:不接受参数
  • OperatorNotExist ("not_exist")
    • 含义:匹配记录不包含字段 {Field}
    • Value格式:不接受参数

demo

{
  "condition": "AND",
  "rules": [
    {
      "field": "price",
      "operator": "less",
      "value": 10.25
    },
    {
      "condition": "OR",
      "rules": [
        {
          "field": "category",
          "operator": "equal",
          "value": 2
        },
        {
          "condition": "AND",
          "rules": [{
            "field": "name",
            "operator": "not_in",
            "value": ["a", "b"]
          }]
        }
      ]
    }
  ]
}

TODO

  • 考虑是否要提供接口与其它条件合并

    一种可选择的方案是,ToMgo之后由用户自行合并

  • 如何提取某个字段的过滤条件呢?

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ConditionAnd = Condition("AND")
	ConditionOr  = Condition("OR")
)
View Source
var (
	OperatorEqual    = Operator("equal")
	OperatorNotEqual = Operator("not_equal")

	// set operator
	OperatorIn    = Operator("in")
	OperatorNotIn = Operator("not_in")

	// numeric compare
	OperatorLess           = Operator("less")
	OperatorLessOrEqual    = Operator("less_or_equal")
	OperatorGreater        = Operator("greater")
	OperatorGreaterOrEqual = Operator("greater_or_equal")

	// datetime operate
	OperatorDatetimeLess           = Operator("datetime_less")
	OperatorDatetimeLessOrEqual    = Operator("datetime_less_or_equal")
	OperatorDatetimeGreater        = Operator("datetime_greater")
	OperatorDatetimeGreaterOrEqual = Operator("datetime_greater_or_equal")

	// string operator
	OperatorBeginsWith    = Operator("begins_with")
	OperatorNotBeginsWith = Operator("not_begins_with")
	OperatorContains      = Operator("contains")
	OperatorNotContains   = Operator("not_contains")
	OperatorsEndsWith     = Operator("ends_with")
	OperatorNotEndsWith   = Operator("not_ends_with")

	// array operator
	OperatorIsEmpty    = Operator("is_empty")
	OperatorIsNotEmpty = Operator("is_not_empty")

	// null check
	OperatorIsNull    = Operator("is_null")
	OperatorIsNotNull = Operator("is_not_null")

	// exist check
	OperatorExist    = Operator("exist")
	OperatorNotExist = Operator("not_exist")
)
View Source
var (
	TypeNumeric = "numeric"
	TypeBoolean = "boolean"
	TypeString  = "string"
	TypeUnknown = "unknown"
)
View Source
var (
	// 嵌套层级的深度按树的高度计算,查询条件最大深度为3即最多嵌套2层
	MaxDeep = 3
)
View Source
var (
	// TODO: should we support dot field separator here?
	ValidFieldPattern = regexp.MustCompile(`^[a-zA-Z0-9][\d\w\-_.]*$`)
)

Functions

func MapToQueryFilterHookFunc

func MapToQueryFilterHookFunc() mapstructure.DecodeHookFunc

Types

type AtomRule

type AtomRule struct {
	Field    string      `json:"field"`
	Operator Operator    `json:"operator"`
	Value    interface{} `json:"value"`
}

*************** define rule ************************

func (AtomRule) GetDeep

func (r AtomRule) GetDeep() int

func (AtomRule) Match

func (r AtomRule) Match(matcher Matcher) bool

func (AtomRule) ToMgo

func (r AtomRule) ToMgo() (mgoFiler map[string]interface{}, key string, err error)

ToMgo generate mongo filter from rule

func (AtomRule) Validate

func (r AtomRule) Validate() (string, error)

type CombinedRule

type CombinedRule struct {
	Condition Condition `json:"condition"`
	Rules     []Rule    `json:"rules"`
}

*************** define query ************************

func (CombinedRule) GetDeep

func (r CombinedRule) GetDeep() int

func (CombinedRule) Match

func (r CombinedRule) Match(matcher Matcher) bool

func (CombinedRule) ToMgo

func (r CombinedRule) ToMgo() (mgoFilter map[string]interface{}, key string, err error)

func (CombinedRule) Validate

func (r CombinedRule) Validate() (string, error)

type Condition

type Condition string

*************** define condition ************************

func (Condition) ToMgo

func (c Condition) ToMgo() (mgoOperator string, err error)

func (Condition) Validate

func (c Condition) Validate() error

type Matcher

type Matcher func(r AtomRule) bool

type Operator

type Operator string

*************** define operator ************************

func (Operator) Validate

func (op Operator) Validate() error

type QueryFilter

type QueryFilter struct {
	Rule `json:",inline"`
}

QueryFilter is aimed at export as a struct member

func (*QueryFilter) MarshalJSON

func (qf *QueryFilter) MarshalJSON() ([]byte, error)

func (*QueryFilter) UnmarshalJSON

func (qf *QueryFilter) UnmarshalJSON(raw []byte) error

func (*QueryFilter) Validate

func (qf *QueryFilter) Validate() (string, error)

type Rule

type Rule interface {
	GetDeep() int
	Validate() (string, error)
	ToMgo() (mgoFilter map[string]interface{}, errKey string, err error)
	Match(matcher Matcher) bool
}

func ParseRule

func ParseRule(data map[string]interface{}) (queryFilter Rule, errKey string, err error)

func ParseRuleFromBytes

func ParseRuleFromBytes(bs []byte) (queryFilter Rule, errKey string, err error)

type RuleGroup

type RuleGroup struct {
	Condition Condition                `json:"condition" field:"condition"`
	Rules     []map[string]interface{} `json:"rules" field:"rules"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL