mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2025-09-23 01:23:36 +08:00
support basic json filtering and selection
This commit is contained in:
@@ -1,5 +1,107 @@
|
||||
package json
|
||||
|
||||
func QueryJson(jsonLine string, query string) (jsonOutput string) {
|
||||
return jsonLine
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/chrislusf/seaweedfs/weed/query/sqltypes"
|
||||
"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
|
||||
}
|
||||
|
||||
func filterJson(jsonLine string, query Query) bool{
|
||||
|
||||
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
|
||||
|
||||
}
|
||||
|
@@ -58,7 +58,7 @@ func TestGjson(t *testing.T) {
|
||||
projections := []string{"quiz","fruit"}
|
||||
|
||||
gjson.ForEachLine(data, func(line gjson.Result) bool{
|
||||
println(line.String())
|
||||
println(line.Raw)
|
||||
println("+++++++++++")
|
||||
results := gjson.GetMany(line.Raw, projections...)
|
||||
for _, result := range results {
|
||||
@@ -71,3 +71,66 @@ func TestGjson(t *testing.T) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
func TestJsonQueryRow(t *testing.T) {
|
||||
|
||||
data := `
|
||||
{
|
||||
"fruit": "Bl\"ue",
|
||||
"size": 6,
|
||||
"quiz": "green"
|
||||
}
|
||||
|
||||
`
|
||||
selections := []string{"fruit", "size"}
|
||||
|
||||
isFiltered, values := QueryJson(data, selections, Query{
|
||||
Field: "quiz",
|
||||
Op: "=",
|
||||
Value: "green",
|
||||
})
|
||||
|
||||
if !isFiltered {
|
||||
t.Errorf("should have been filtered")
|
||||
}
|
||||
|
||||
if values == nil {
|
||||
t.Errorf("values should have been returned")
|
||||
}
|
||||
|
||||
buf := ToJson(nil, selections, values)
|
||||
println(string(buf))
|
||||
|
||||
}
|
||||
|
||||
func TestJsonQueryNumber(t *testing.T) {
|
||||
|
||||
data := `
|
||||
{
|
||||
"fruit": "Bl\"ue",
|
||||
"size": 6,
|
||||
"quiz": "green"
|
||||
}
|
||||
|
||||
`
|
||||
selections := []string{"fruit", "quiz"}
|
||||
|
||||
isFiltered, values := QueryJson(data, selections, Query{
|
||||
Field: "size",
|
||||
Op: ">=",
|
||||
Value: "6",
|
||||
})
|
||||
|
||||
if !isFiltered {
|
||||
t.Errorf("should have been filtered")
|
||||
}
|
||||
|
||||
if values == nil {
|
||||
t.Errorf("values should have been returned")
|
||||
}
|
||||
|
||||
buf := ToJson(nil, selections, values)
|
||||
println(string(buf))
|
||||
|
||||
}
|
||||
|
||||
|
17
weed/query/json/seralize.go
Normal file
17
weed/query/json/seralize.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package json
|
||||
|
||||
import "github.com/chrislusf/seaweedfs/weed/query/sqltypes"
|
||||
|
||||
func ToJson(buf []byte, selections []string, values []sqltypes.Value) []byte {
|
||||
buf = append(buf, '{')
|
||||
for i, value := range values {
|
||||
if i > 0 {
|
||||
buf = append(buf, ',')
|
||||
}
|
||||
buf = append(buf, selections[i]...)
|
||||
buf = append(buf, ':')
|
||||
buf = append(buf, value.Raw()...)
|
||||
}
|
||||
buf = append(buf, '}')
|
||||
return buf
|
||||
}
|
Reference in New Issue
Block a user