func strEndsWith(x, y interface{}) (bool, error) {
	xv, okX := x.(string)
	if !okX {
		return false, fmt.Errorf("%v must be string", x)
	}
	yv, okY := y.(string)
	if !okY {
		return false, fmt.Errorf("%v must be string", y)
	}
	return strings.HasSuffix(xv, yv), nil
}
strEndsWith checks if x ends with y
package gojsonq
import (
	"fmt"
	"reflect"
	"strings"
)
const (
	operatorEq             = "="
	operatorEqEng          = "eq"
	operatorNotEq          = "!="
	operatorNotEqEng       = "neq"
	operatorNotEqAnother   = "<>"
	operatorGt             = ">"
	operatorGtEng          = "gt"
	operatorLt             = "<"
	operatorLtEng          = "lt"
	operatorGtE            = ">="
	operatorGtEEng         = "gte"
	operatorLtE            = "<="
	operatorLtEEng         = "lte"
	operatorStrictContains = "strictContains"
	operatorContains       = "contains"
	operatorEndsWith       = "endsWith"
	operatorStartsWith     = "startsWith"
	operatorIn             = "in"
	operatorNotIn          = "notIn"
	operatorLenEq          = "leneq"
	operatorLenNotEq       = "lenneq"
	operatorLenGt          = "lengt"
	operatorLenGte         = "lengte"
	operatorLenLt          = "lenlt"
	operatorLenLte         = "lenlte"
)
func defaultQueries() map[string]QueryFunc {
	return map[string]QueryFunc{
		operatorEq:             eq,
		operatorEqEng:          eq,
		operatorNotEq:          neq,
		operatorNotEqEng:       neq,
		operatorNotEqAnother:   neq,
		operatorGt:             gt,
		operatorGtEng:          gt,
		operatorLt:             lt,
		operatorLtEng:          lt,
		operatorGtE:            gte,
		operatorGtEEng:         gte,
		operatorLtE:            lte,
		operatorLtEEng:         lte,
		operatorStrictContains: strStrictContains,
		operatorContains:       strContains,
		operatorStartsWith:     strStartsWith,
		operatorEndsWith:       strEndsWith,
		operatorIn:             in,
		operatorNotIn:          notIn,
		operatorLenEq:          lenEq,
		operatorLenNotEq:       lenNotEq,
		operatorLenGt:          lenGt,
		operatorLenGte:         lenGte,
		operatorLenLt:          lenLt,
		operatorLenLte:         lenLte,
	}
}
type QueryFunc func(x, y interface{}) (bool, error)
func eq(x, y interface{}) (bool, error) {
	if fv, ok := toFloat64(y); ok {
		y = fv
	}
	return reflect.DeepEqual(x, y), nil
}
func neq(x, y interface{}) (bool, error) {
	b, err := eq(x, y)
	return !b, err
}
func gt(x, y interface{}) (bool, error) {
	xv, ok := x.(float64)
	if !ok {
		return false, fmt.Errorf("%v must be numeric", x)
	}
	if fv, ok := toFloat64(y); ok {
		return xv > fv, nil
	}
	return false, nil
}
func lt(x, y interface{}) (bool, error) {
	xv, ok := x.(float64)
	if !ok {
		return false, fmt.Errorf("%v must be numeric", x)
	}
	if fv, ok := toFloat64(y); ok {
		return xv < fv, nil
	}
	return false, nil
}
func gte(x, y interface{}) (bool, error) {
	xv, ok := x.(float64)
	if !ok {
		return false, fmt.Errorf("%v must be numeric", x)
	}
	if fv, ok := toFloat64(y); ok {
		return xv >= fv, nil
	}
	return false, nil
}
func lte(x, y interface{}) (bool, error) {
	xv, ok := x.(float64)
	if !ok {
		return false, fmt.Errorf("%v must be numeric", x)
	}
	if fv, ok := toFloat64(y); ok {
		return xv <= fv, nil
	}
	return false, nil
}
func strStrictContains(x, y interface{}) (bool, error) {
	xv, okX := x.(string)
	if !okX {
		return false, fmt.Errorf("%v must be string", x)
	}
	yv, okY := y.(string)
	if !okY {
		return false, fmt.Errorf("%v must be string", y)
	}
	return strings.Contains(xv, yv), nil
}
func strContains(x, y interface{}) (bool, error) {
	xv, okX := x.(string)
	if !okX {
		return false, fmt.Errorf("%v must be string", x)
	}
	yv, okY := y.(string)
	if !okY {
		return false, fmt.Errorf("%v must be string", y)
	}
	return strings.Contains(strings.ToLower(xv), strings.ToLower(yv)), nil
}
func strStartsWith(x, y interface{}) (bool, error) {
	xv, okX := x.(string)
	if !okX {
		return false, fmt.Errorf("%v must be string", x)
	}
	yv, okY := y.(string)
	if !okY {
		return false, fmt.Errorf("%v must be string", y)
	}
	return strings.HasPrefix(xv, yv), nil
}