2019-10-02 19:06:03 +00:00
|
|
|
package json
|
|
|
|
|
2019-10-07 05:35:05 +00:00
|
|
|
import (
|
|
|
|
"strconv"
|
|
|
|
|
2022-07-29 07:17:28 +00:00
|
|
|
"github.com/seaweedfs/seaweedfs/weed/query/sqltypes"
|
2019-10-07 05:35:05 +00:00
|
|
|
"github.com/tidwall/gjson"
|
|
|
|
"github.com/tidwall/match"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Query struct {
|
|
|
|
Field string
|
|
|
|
Op string
|
|
|
|
Value string
|
|
|
|
}
|
|
|
|
|
|
|
|
func QueryJson(jsonLine string, projections []string, query Query) (passedFilter bool, values []sqltypes.Value) {
|
|
|
|
if filterJson(jsonLine, query) {
|
|
|
|
passedFilter = true
|
|
|
|
fields := gjson.GetMany(jsonLine, projections...)
|
|
|
|
for _, f := range fields {
|
|
|
|
values = append(values, sqltypes.MakeTrusted(sqltypes.Type(f.Type), sqltypes.StringToBytes(f.Raw)))
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
2019-10-09 07:03:18 +00:00
|
|
|
func filterJson(jsonLine string, query Query) bool {
|
2019-10-07 05:35:05 +00:00
|
|
|
|
|
|
|
value := gjson.Get(jsonLine, query.Field)
|
|
|
|
|
|
|
|
// copied from gjson.go queryMatches() function
|
|
|
|
rpv := query.Value
|
|
|
|
|
|
|
|
if !value.Exists() {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if query.Op == "" {
|
|
|
|
// the query is only looking for existence, such as:
|
|
|
|
// friends.#(name)
|
|
|
|
// which makes sure that the array "friends" has an element of
|
|
|
|
// "name" that exists
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
switch value.Type {
|
|
|
|
case gjson.String:
|
|
|
|
switch query.Op {
|
|
|
|
case "=":
|
|
|
|
return value.Str == rpv
|
|
|
|
case "!=":
|
|
|
|
return value.Str != rpv
|
|
|
|
case "<":
|
|
|
|
return value.Str < rpv
|
|
|
|
case "<=":
|
|
|
|
return value.Str <= rpv
|
|
|
|
case ">":
|
|
|
|
return value.Str > rpv
|
|
|
|
case ">=":
|
|
|
|
return value.Str >= rpv
|
|
|
|
case "%":
|
|
|
|
return match.Match(value.Str, rpv)
|
|
|
|
case "!%":
|
|
|
|
return !match.Match(value.Str, rpv)
|
|
|
|
}
|
|
|
|
case gjson.Number:
|
|
|
|
rpvn, _ := strconv.ParseFloat(rpv, 64)
|
|
|
|
switch query.Op {
|
|
|
|
case "=":
|
|
|
|
return value.Num == rpvn
|
|
|
|
case "!=":
|
|
|
|
return value.Num != rpvn
|
|
|
|
case "<":
|
|
|
|
return value.Num < rpvn
|
|
|
|
case "<=":
|
|
|
|
return value.Num <= rpvn
|
|
|
|
case ">":
|
|
|
|
return value.Num > rpvn
|
|
|
|
case ">=":
|
|
|
|
return value.Num >= rpvn
|
|
|
|
}
|
|
|
|
case gjson.True:
|
|
|
|
switch query.Op {
|
|
|
|
case "=":
|
|
|
|
return rpv == "true"
|
|
|
|
case "!=":
|
|
|
|
return rpv != "true"
|
|
|
|
case ">":
|
|
|
|
return rpv == "false"
|
|
|
|
case ">=":
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
case gjson.False:
|
|
|
|
switch query.Op {
|
|
|
|
case "=":
|
|
|
|
return rpv == "false"
|
|
|
|
case "!=":
|
|
|
|
return rpv != "false"
|
|
|
|
case "<":
|
|
|
|
return rpv == "true"
|
|
|
|
case "<=":
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
|
2019-10-02 19:06:03 +00:00
|
|
|
}
|