478 lines
9.8 KiB
Go
478 lines
9.8 KiB
Go
package engine
|
||
|
||
import (
|
||
"fmt"
|
||
"math"
|
||
"reflect"
|
||
"regexp"
|
||
"strconv"
|
||
"strings"
|
||
"time"
|
||
|
||
"git.kingecg.top/kingecg/gomog/pkg/types"
|
||
)
|
||
|
||
// ========== 类型转换辅助函数 ==========
|
||
|
||
// ToFloat64 将任意值转换为 float64(导出版本)
|
||
func ToFloat64(v interface{}) float64 {
|
||
return toFloat64(v)
|
||
}
|
||
|
||
// toFloat64 将值转换为 float64
|
||
func toFloat64(v interface{}) float64 {
|
||
switch val := v.(type) {
|
||
case int:
|
||
return float64(val)
|
||
case int8:
|
||
return float64(val)
|
||
case int16:
|
||
return float64(val)
|
||
case int32:
|
||
return float64(val)
|
||
case int64:
|
||
return float64(val)
|
||
case uint:
|
||
return float64(val)
|
||
case uint8:
|
||
return float64(val)
|
||
case uint16:
|
||
return float64(val)
|
||
case uint32:
|
||
return float64(val)
|
||
case uint64:
|
||
return float64(val)
|
||
case float32:
|
||
return float64(val)
|
||
case float64:
|
||
return val
|
||
case string:
|
||
if num, err := strconv.ParseFloat(val, 64); err == nil {
|
||
return num
|
||
}
|
||
}
|
||
return 0
|
||
}
|
||
|
||
// ToInt64 将任意值转换为 int64(导出版本)
|
||
func ToInt64(v interface{}) int64 {
|
||
return toInt64(v)
|
||
}
|
||
|
||
// toInt64 将值转换为 int64
|
||
func toInt64(v interface{}) int64 {
|
||
switch val := v.(type) {
|
||
case int:
|
||
return int64(val)
|
||
case int8:
|
||
return int64(val)
|
||
case int16:
|
||
return int64(val)
|
||
case int32:
|
||
return int64(val)
|
||
case int64:
|
||
return val
|
||
case uint:
|
||
return int64(val)
|
||
case uint8:
|
||
return int64(val)
|
||
case uint16:
|
||
return int64(val)
|
||
case uint32:
|
||
return int64(val)
|
||
case uint64:
|
||
return int64(val)
|
||
case float32:
|
||
return int64(val)
|
||
case float64:
|
||
return int64(val)
|
||
case string:
|
||
if num, err := strconv.ParseInt(val, 10, 64); err == nil {
|
||
return num
|
||
}
|
||
}
|
||
return 0
|
||
}
|
||
|
||
// FormatValueToString 将任意值格式化为字符串(导出版本)
|
||
func FormatValueToString(value interface{}) string {
|
||
return formatValueToString(value)
|
||
}
|
||
|
||
// formatValueToString 将任意值格式化为字符串
|
||
func formatValueToString(value interface{}) string {
|
||
if value == nil {
|
||
return ""
|
||
}
|
||
|
||
switch v := value.(type) {
|
||
case string:
|
||
return v
|
||
case bool:
|
||
return strconv.FormatBool(v)
|
||
case int, int8, int16, int32, int64:
|
||
return fmt.Sprintf("%d", v)
|
||
case uint, uint8, uint16, uint32, uint64:
|
||
return fmt.Sprintf("%d", v)
|
||
case float32:
|
||
return strconv.FormatFloat(float64(v), 'g', -1, 32)
|
||
case float64:
|
||
return strconv.FormatFloat(v, 'g', -1, 64)
|
||
case time.Time:
|
||
return v.Format(time.RFC3339)
|
||
case []interface{}:
|
||
result := "["
|
||
for i, item := range v {
|
||
if i > 0 {
|
||
result += ","
|
||
}
|
||
result += formatValueToString(item)
|
||
}
|
||
result += "]"
|
||
return result
|
||
case map[string]interface{}:
|
||
result := "{"
|
||
first := true
|
||
for k, val := range v {
|
||
if !first {
|
||
result += ","
|
||
}
|
||
result += fmt.Sprintf("%s:%v", k, val)
|
||
first = false
|
||
}
|
||
result += "}"
|
||
return result
|
||
default:
|
||
return fmt.Sprintf("%v", v)
|
||
}
|
||
}
|
||
|
||
// IsTrueValue 检查值是否为真值(导出版本)
|
||
// 注意:内部使用的 isTrueValue/isTrue 已在 query.go 和 aggregate.go 中定义
|
||
func IsTrueValue(v interface{}) bool {
|
||
// 使用统一的转换逻辑
|
||
if v == nil {
|
||
return false
|
||
}
|
||
|
||
switch val := v.(type) {
|
||
case bool:
|
||
return val
|
||
case int, int8, int16, int32, int64:
|
||
return ToInt64(v) != 0
|
||
case uint, uint8, uint16, uint32, uint64:
|
||
return ToInt64(v) != 0
|
||
case float32, float64:
|
||
return ToFloat64(v) != 0
|
||
case string:
|
||
return val != "" && val != "0" && strings.ToLower(val) != "false"
|
||
case []interface{}:
|
||
return len(val) > 0
|
||
case map[string]interface{}:
|
||
return len(val) > 0
|
||
default:
|
||
return true
|
||
}
|
||
}
|
||
|
||
// ========== 文档操作辅助函数 ==========
|
||
|
||
// GetNestedValue 从嵌套 map 中获取值
|
||
func GetNestedValue(data map[string]interface{}, field string) interface{} {
|
||
if field == "" {
|
||
return nil
|
||
}
|
||
|
||
parts := strings.Split(field, ".")
|
||
current := data
|
||
|
||
for i, part := range parts {
|
||
if i == len(parts)-1 {
|
||
return current[part]
|
||
}
|
||
|
||
if next, ok := current[part].(map[string]interface{}); ok {
|
||
current = next
|
||
} else {
|
||
return nil
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// SetNestedValue 设置嵌套 map 中的值
|
||
func SetNestedValue(data map[string]interface{}, field string, value interface{}) {
|
||
if field == "" {
|
||
return
|
||
}
|
||
|
||
parts := strings.Split(field, ".")
|
||
current := data
|
||
|
||
for i, part := range parts {
|
||
if i == len(parts)-1 {
|
||
current[part] = value
|
||
return
|
||
}
|
||
|
||
if next, ok := current[part].(map[string]interface{}); ok {
|
||
current = next
|
||
} else {
|
||
newMap := make(map[string]interface{})
|
||
current[part] = newMap
|
||
current = newMap
|
||
}
|
||
}
|
||
}
|
||
|
||
// RemoveNestedValue 移除嵌套 map 中的值
|
||
func RemoveNestedValue(data map[string]interface{}, field string) {
|
||
if field == "" {
|
||
return
|
||
}
|
||
|
||
parts := strings.Split(field, ".")
|
||
current := data
|
||
|
||
for i, part := range parts {
|
||
if i == len(parts)-1 {
|
||
delete(current, part)
|
||
return
|
||
}
|
||
|
||
if next, ok := current[part].(map[string]interface{}); ok {
|
||
current = next
|
||
} else {
|
||
return
|
||
}
|
||
}
|
||
}
|
||
|
||
// DeepCopyMap 深度复制 map
|
||
func DeepCopyMap(src map[string]interface{}) map[string]interface{} {
|
||
dst := make(map[string]interface{})
|
||
for k, v := range src {
|
||
dst[k] = deepCopyValue(v)
|
||
}
|
||
return dst
|
||
}
|
||
|
||
// deepCopyValue 深度复制值
|
||
func deepCopyValue(v interface{}) interface{} {
|
||
switch val := v.(type) {
|
||
case map[string]interface{}:
|
||
return DeepCopyMap(val)
|
||
case []interface{}:
|
||
arr := make([]interface{}, len(val))
|
||
for i, item := range val {
|
||
arr[i] = deepCopyValue(item)
|
||
}
|
||
return arr
|
||
default:
|
||
return v
|
||
}
|
||
}
|
||
|
||
// ========== 比较辅助函数 ==========
|
||
|
||
// CompareEq 相等比较(导出版本)
|
||
func CompareEq(a, b interface{}) bool {
|
||
if a == nil && b == nil {
|
||
return true
|
||
}
|
||
if a == nil || b == nil {
|
||
return false
|
||
}
|
||
|
||
if isComplexType(a) || isComplexType(b) {
|
||
return reflect.DeepEqual(a, b)
|
||
}
|
||
|
||
return normalizeValue(a) == normalizeValue(b)
|
||
}
|
||
|
||
// CompareNumbers 比较两个数值,返回 -1/0/1(导出版本)
|
||
func CompareNumbers(a, b interface{}) int {
|
||
return compareNumbers(a, b)
|
||
}
|
||
|
||
// compareNumbers 比较两个数值
|
||
func compareNumbers(a, b interface{}) int {
|
||
numA := toFloat64(a)
|
||
numB := toFloat64(b)
|
||
|
||
if numA < numB {
|
||
return -1
|
||
} else if numA > numB {
|
||
return 1
|
||
}
|
||
return 0
|
||
}
|
||
|
||
// IsComplexType 检查是否是复杂类型(导出版本)
|
||
func IsComplexType(v interface{}) bool {
|
||
return isComplexType(v)
|
||
}
|
||
|
||
// isComplexType 检查是否是复杂类型
|
||
func isComplexType(v interface{}) bool {
|
||
switch v.(type) {
|
||
case []interface{}:
|
||
return true
|
||
case map[string]interface{}:
|
||
return true
|
||
case map[interface{}]interface{}:
|
||
return true
|
||
default:
|
||
return false
|
||
}
|
||
}
|
||
|
||
// NormalizeValue 标准化值用于比较(导出版本)
|
||
func NormalizeValue(v interface{}) interface{} {
|
||
return normalizeValue(v)
|
||
}
|
||
|
||
// normalizeValue 标准化值
|
||
func normalizeValue(v interface{}) interface{} {
|
||
if v == nil {
|
||
return nil
|
||
}
|
||
|
||
switch val := v.(type) {
|
||
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64:
|
||
return toFloat64(v)
|
||
case string:
|
||
if num, err := strconv.ParseFloat(val, 64); err == nil {
|
||
return num
|
||
}
|
||
return strings.ToLower(val)
|
||
}
|
||
|
||
return v
|
||
}
|
||
|
||
// ========== 数组辅助函数 ==========
|
||
|
||
// ContainsElement 检查数组是否包含指定元素
|
||
func ContainsElement(arr []interface{}, element interface{}) bool {
|
||
for _, item := range arr {
|
||
if compareEq(item, element) {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
// ContainsAllElements 检查数组是否包含所有指定元素
|
||
func ContainsAllElements(arr []interface{}, elements []interface{}) bool {
|
||
for _, elem := range elements {
|
||
if !ContainsElement(arr, elem) {
|
||
return false
|
||
}
|
||
}
|
||
return true
|
||
}
|
||
|
||
// ArrayIntersection 计算数组交集
|
||
func ArrayIntersection(a, b []interface{}) []interface{} {
|
||
result := make([]interface{}, 0)
|
||
for _, item := range a {
|
||
if ContainsElement(b, item) && !ContainsElement(result, item) {
|
||
result = append(result, item)
|
||
}
|
||
}
|
||
return result
|
||
}
|
||
|
||
// ArrayUnion 计算数组并集
|
||
func ArrayUnion(a, b []interface{}) []interface{} {
|
||
result := make([]interface{}, len(a))
|
||
copy(result, a)
|
||
for _, item := range b {
|
||
if !ContainsElement(result, item) {
|
||
result = append(result, item)
|
||
}
|
||
}
|
||
return result
|
||
}
|
||
|
||
// ========== 正则表达式辅助函数 ==========
|
||
|
||
// MatchRegex 正则表达式匹配
|
||
func MatchRegex(value interface{}, pattern interface{}) bool {
|
||
str, ok := value.(string)
|
||
if !ok {
|
||
return false
|
||
}
|
||
|
||
patternStr, ok := pattern.(string)
|
||
if !ok {
|
||
return false
|
||
}
|
||
|
||
matched, _ := regexp.MatchString(patternStr, str)
|
||
return matched
|
||
}
|
||
|
||
// ========== 类型检查辅助函数 ==========
|
||
|
||
// CheckType 检查值的类型
|
||
func CheckType(value interface{}, typeName string) bool {
|
||
if value == nil {
|
||
return typeName == "null"
|
||
}
|
||
|
||
var actualType string
|
||
switch reflect.TypeOf(value).Kind() {
|
||
case reflect.String:
|
||
actualType = "string"
|
||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||
actualType = "int"
|
||
case reflect.Float32, reflect.Float64:
|
||
actualType = "double"
|
||
case reflect.Bool:
|
||
actualType = "bool"
|
||
case reflect.Slice, reflect.Array:
|
||
actualType = "array"
|
||
case reflect.Map:
|
||
actualType = "object"
|
||
}
|
||
|
||
return actualType == typeName
|
||
}
|
||
|
||
// ========== 数学辅助函数 ==========
|
||
|
||
// RoundToPrecision 四舍五入到指定精度
|
||
func RoundToPrecision(value float64, precision int) float64 {
|
||
multiplier := math.Pow(10, float64(precision))
|
||
return math.Round(value*multiplier) / multiplier
|
||
}
|
||
|
||
// ========== 文档辅助函数 ==========
|
||
|
||
// GetFieldValue 从文档中获取字段值
|
||
func GetFieldValue(doc types.Document, field interface{}) interface{} {
|
||
switch f := field.(type) {
|
||
case string:
|
||
if strings.HasPrefix(f, "$") {
|
||
return GetNestedValue(doc.Data, f[1:])
|
||
}
|
||
return GetNestedValue(doc.Data, f)
|
||
default:
|
||
return nil
|
||
}
|
||
}
|
||
|
||
// GetFieldValueStr 从文档中获取字段值的字符串形式
|
||
func GetFieldValueStr(doc types.Document, field interface{}) string {
|
||
val := GetFieldValue(doc, field)
|
||
if str, ok := val.(string); ok {
|
||
return str
|
||
}
|
||
return toString(val)
|
||
}
|