gomog/internal/engine/helpers.go

478 lines
9.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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