diff options
| author | Chris Lu <chris.lu@gmail.com> | 2019-10-06 22:35:05 -0700 |
|---|---|---|
| committer | Chris Lu <chris.lu@gmail.com> | 2019-10-06 22:35:08 -0700 |
| commit | f8d4b7d1c01eecb54edc4169d6b8a0d3c39a730c (patch) | |
| tree | e463982066e42bdabeae7cff5e0569c0874b4c39 /weed/query | |
| parent | e26670c67ad27301dcfd597c94f5fce9b5cd6331 (diff) | |
| download | seaweedfs-f8d4b7d1c01eecb54edc4169d6b8a0d3c39a730c.tar.xz seaweedfs-f8d4b7d1c01eecb54edc4169d6b8a0d3c39a730c.zip | |
support basic json filtering and selection
Diffstat (limited to 'weed/query')
| -rw-r--r-- | weed/query/json/query_json.go | 106 | ||||
| -rw-r--r-- | weed/query/json/query_json_test.go | 65 | ||||
| -rw-r--r-- | weed/query/json/seralize.go | 17 |
3 files changed, 185 insertions, 3 deletions
diff --git a/weed/query/json/query_json.go b/weed/query/json/query_json.go index 779aa96e9..b061df97d 100644 --- a/weed/query/json/query_json.go +++ b/weed/query/json/query_json.go @@ -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 + } diff --git a/weed/query/json/query_json_test.go b/weed/query/json/query_json_test.go index 7ad837360..621d4f548 100644 --- a/weed/query/json/query_json_test.go +++ b/weed/query/json/query_json_test.go @@ -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)) + +} + diff --git a/weed/query/json/seralize.go b/weed/query/json/seralize.go new file mode 100644 index 000000000..9bbddc2ff --- /dev/null +++ b/weed/query/json/seralize.go @@ -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 +} |
