gomog/internal/engine/query.go

220 lines
4.3 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
}
case "$mod":
if !compareMod(value, operand) {
return false
}
case "$bitsAllClear":
if !compareBitsAllClear(value, operand) {
return false
}
case "$bitsAllSet":
if !compareBitsAllSet(value, operand) {
return false
}
case "$bitsAnyClear":
if !compareBitsAnyClear(value, operand) {
return false
}
case "$bitsAnySet":
if !compareBitsAnySet(value, operand) {
return false
}
default:
// 未知操作符,跳过
}
}
return true
}