200 lines
3.9 KiB
Go
200 lines
3.9 KiB
Go
package engine
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"git.kingecg.top/kingecg/gomog/pkg/types"
|
|
)
|
|
|
|
// MatchFilter 匹配过滤器
|
|
func MatchFilter(doc map[string]interface{}, filter types.Filter) bool {
|
|
if filter == nil || len(filter) == 0 {
|
|
return true
|
|
}
|
|
|
|
for key, condition := range filter {
|
|
switch key {
|
|
case "$and":
|
|
if !handleAnd(doc, condition) {
|
|
return false
|
|
}
|
|
case "$or":
|
|
if !handleOr(doc, condition) {
|
|
return false
|
|
}
|
|
case "$nor":
|
|
if !handleNor(doc, condition) {
|
|
return false
|
|
}
|
|
case "$not":
|
|
if !handleNot(doc, condition) {
|
|
return false
|
|
}
|
|
default:
|
|
if !matchField(doc, key, condition) {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
// handleAnd 处理 $and 操作符
|
|
func handleAnd(doc map[string]interface{}, condition interface{}) bool {
|
|
andConditions, ok := condition.([]interface{})
|
|
if !ok {
|
|
return false
|
|
}
|
|
|
|
for _, cond := range andConditions {
|
|
if condMap, ok := cond.(map[string]interface{}); ok {
|
|
if !MatchFilter(doc, condMap) {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// handleOr 处理 $or 操作符
|
|
func handleOr(doc map[string]interface{}, condition interface{}) bool {
|
|
orConditions, ok := condition.([]interface{})
|
|
if !ok {
|
|
return false
|
|
}
|
|
|
|
for _, cond := range orConditions {
|
|
if condMap, ok := cond.(map[string]interface{}); ok {
|
|
if MatchFilter(doc, condMap) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// handleNor 处理 $nor 操作符
|
|
func handleNor(doc map[string]interface{}, condition interface{}) bool {
|
|
orConditions, ok := condition.([]interface{})
|
|
if !ok {
|
|
return false
|
|
}
|
|
|
|
for _, cond := range orConditions {
|
|
if condMap, ok := cond.(map[string]interface{}); ok {
|
|
if MatchFilter(doc, condMap) {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// handleNot 处理 $not 操作符
|
|
func handleNot(doc map[string]interface{}, condition interface{}) bool {
|
|
if condMap, ok := condition.(map[string]interface{}); ok {
|
|
return !MatchFilter(doc, condMap)
|
|
}
|
|
return true
|
|
}
|
|
|
|
// matchField 匹配字段
|
|
func matchField(doc map[string]interface{}, key string, condition interface{}) bool {
|
|
value := getNestedValue(doc, key)
|
|
|
|
// 处理操作符条件
|
|
if condMap, ok := condition.(map[string]interface{}); ok {
|
|
return evaluateOperators(value, condMap)
|
|
}
|
|
|
|
// 简单相等比较
|
|
return compareEq(value, condition)
|
|
}
|
|
|
|
// getNestedValue 获取嵌套字段值(支持 "a.b.c" 格式)
|
|
func getNestedValue(doc map[string]interface{}, key string) interface{} {
|
|
parts := strings.Split(key, ".")
|
|
var current interface{} = doc
|
|
|
|
for _, part := range parts {
|
|
if m, ok := current.(map[string]interface{}); ok {
|
|
current = m[part]
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
return current
|
|
}
|
|
|
|
// evaluateOperators 评估操作符
|
|
func evaluateOperators(value interface{}, operators map[string]interface{}) bool {
|
|
for op, operand := range operators {
|
|
switch op {
|
|
case "$eq":
|
|
if !compareEq(value, operand) {
|
|
return false
|
|
}
|
|
case "$ne":
|
|
if compareEq(value, operand) {
|
|
return false
|
|
}
|
|
case "$gt":
|
|
if !compareGt(value, operand) {
|
|
return false
|
|
}
|
|
case "$gte":
|
|
if !compareGte(value, operand) {
|
|
return false
|
|
}
|
|
case "$lt":
|
|
if !compareLt(value, operand) {
|
|
return false
|
|
}
|
|
case "$lte":
|
|
if !compareLte(value, operand) {
|
|
return false
|
|
}
|
|
case "$in":
|
|
if !compareIn(value, operand) {
|
|
return false
|
|
}
|
|
case "$nin":
|
|
if compareIn(value, operand) {
|
|
return false
|
|
}
|
|
case "$regex":
|
|
if !compareRegex(value, operand) {
|
|
return false
|
|
}
|
|
case "$exists":
|
|
exists := value != nil
|
|
if operandBool, ok := operand.(bool); ok {
|
|
if exists != operandBool {
|
|
return false
|
|
}
|
|
}
|
|
case "$type":
|
|
if !compareType(value, operand) {
|
|
return false
|
|
}
|
|
case "$all":
|
|
if !compareAll(value, operand) {
|
|
return false
|
|
}
|
|
case "$elemMatch":
|
|
if !compareElemMatch(value, operand) {
|
|
return false
|
|
}
|
|
case "$size":
|
|
if !compareSize(value, operand) {
|
|
return false
|
|
}
|
|
default:
|
|
// 未知操作符,跳过
|
|
}
|
|
}
|
|
return true
|
|
}
|