You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by as...@apache.org on 2019/06/27 11:53:37 UTC
[servicecomb-kie] 26/29: support combination query
This is an automated email from the ASF dual-hosted git repository.
asifdxtreme pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-kie.git
commit 999a22414e4ff0340d883e28e149d83fcab60648
Author: tian <xi...@gmail.com>
AuthorDate: Wed Jun 19 18:35:34 2019 +0800
support combination query
---
go.mod | 3 +-
pkg/common/common.go | 3 +-
server/dao/kie_api.go | 7 +---
server/dao/kv_test.go | 8 ++--
server/resource/v1/common.go | 31 +++++++++++----
server/resource/v1/common_test.go | 31 +++++++++++++++
server/resource/v1/doc_struct.go | 14 ++++---
server/resource/v1/kv_resource.go | 77 ++++++++++++++-----------------------
server/resource/v1/v1_suite_test.go | 13 +++++++
9 files changed, 113 insertions(+), 74 deletions(-)
diff --git a/go.mod b/go.mod
index d5efedc..6646204 100644
--- a/go.mod
+++ b/go.mod
@@ -4,11 +4,12 @@ require (
github.com/emicklei/go-restful v2.8.0+incompatible
github.com/go-chassis/foundation v0.0.0-20190516083152-b8b2476b6db7
github.com/go-chassis/go-archaius v0.16.0
- github.com/go-chassis/go-chassis v1.4.1
+ github.com/go-chassis/go-chassis v1.4.3
github.com/go-chassis/paas-lager v1.0.2-0.20190328010332-cf506050ddb2
github.com/go-mesh/openlogging v1.0.1-0.20181205082104-3d418c478b2d
github.com/onsi/ginkgo v1.8.0
github.com/onsi/gomega v1.5.0
+ github.com/pkg/errors v0.8.0
github.com/stretchr/testify v1.2.2
github.com/urfave/cli v1.20.0
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c // indirect
diff --git a/pkg/common/common.go b/pkg/common/common.go
index e39dca6..f111bce 100644
--- a/pkg/common/common.go
+++ b/pkg/common/common.go
@@ -19,8 +19,7 @@ package common
//match mode
const (
- MatchGreedy = "greedy"
- MatchExact = "exact"
+ QueryParamQ = "q"
)
//http headers
diff --git a/server/dao/kie_api.go b/server/dao/kie_api.go
index a5cca3d..0e0020d 100644
--- a/server/dao/kie_api.go
+++ b/server/dao/kie_api.go
@@ -191,7 +191,7 @@ func (s *MongodbService) FindKVByLabelID(ctx context.Context, domain, labelID, k
//FindKV get kvs by key, labels
//because labels has a a lot of combination,
-//you can use WithExactLabels to return only one kv which's labels exactly match the criteria
+//you can use WithDepth(0) to return only one kv which's labels exactly match the criteria
func (s *MongodbService) FindKV(ctx context.Context, domain string, options ...FindOption) ([]*model.KVResponse, error) {
opts := FindOptions{}
for _, o := range options {
@@ -208,7 +208,7 @@ func (s *MongodbService) FindKV(ctx context.Context, domain string, options ...F
defer cur.Close(ctx)
kvResp := make([]*model.KVResponse, 0)
- if opts.ExactLabels {
+ if opts.Depth == 0 {
openlogging.Debug("find one key", openlogging.WithTags(
map[string]interface{}{
"key": opts.Key,
@@ -218,9 +218,6 @@ func (s *MongodbService) FindKV(ctx context.Context, domain string, options ...F
))
return cursorToOneKV(ctx, cur, opts.Labels)
}
- if opts.Depth == 0 {
- opts.Depth = 1
- }
for cur.Next(ctx) {
curKV := &model.KVDoc{}
diff --git a/server/dao/kv_test.go b/server/dao/kv_test.go
index efbe6d4..db92857 100644
--- a/server/dao/kv_test.go
+++ b/server/dao/kv_test.go
@@ -132,8 +132,8 @@ var _ = Describe("Kv mongodb service", func() {
It("should not return err", func() {
Expect(err).Should(BeNil())
})
- It("should has 2 records", func() {
- Expect(len(kvs)).Should(Equal(2))
+ It("should has 1 records", func() {
+ Expect(len(kvs)).Should(Equal(1))
})
})
@@ -189,8 +189,8 @@ var _ = Describe("Kv mongodb service", func() {
It("should not return err", func() {
Expect(err).Should(BeNil())
})
- It("should has 2 records", func() {
- Expect(len(kvs)).Should(Equal(2))
+ It("should has 1 records", func() {
+ Expect(len(kvs)).Should(Equal(1))
})
})
diff --git a/server/resource/v1/common.go b/server/resource/v1/common.go
index 48baa22..dcf9901 100644
--- a/server/resource/v1/common.go
+++ b/server/resource/v1/common.go
@@ -22,15 +22,17 @@ import (
"fmt"
"github.com/apache/servicecomb-kie/pkg/common"
"github.com/apache/servicecomb-kie/pkg/model"
+ goRestful "github.com/emicklei/go-restful"
"github.com/go-chassis/go-chassis/server/restful"
"github.com/go-mesh/openlogging"
+ "github.com/pkg/errors"
"strconv"
+ "strings"
)
//const of server
const (
MsgDomainMustNotBeEmpty = "domain must not be empty"
- MsgIllegalFindPolicy = "value of header " + common.HeaderMatch + " can be greedy or exact"
MsgIllegalLabels = "label's value can not be empty, " +
"label can not be duplicated, please check your query parameters"
MsgIllegalDepth = "X-Depth must be number"
@@ -55,14 +57,27 @@ func ReadFindDepth(context *restful.Context) (int, error) {
return depth, nil
}
-//ReadMatchPolicy get match policy
-func ReadMatchPolicy(context *restful.Context) string {
- policy := context.ReadRestfulRequest().HeaderParameter(common.HeaderMatch)
- if policy == "" {
- //default is exact to reduce network traffic
- return common.MatchExact
+//ReadLabelCombinations get query combination from url
+//q=app:default+service:payment&q=app:default
+func ReadLabelCombinations(req *goRestful.Request) ([]map[string]string, error) {
+ queryCombinations := req.QueryParameters(common.QueryParamQ)
+ labelCombinations := make([]map[string]string, 0)
+ for _, queryStr := range queryCombinations {
+ labelStr := strings.Split(queryStr, " ")
+ labels := make(map[string]string, len(labelStr))
+ for _, label := range labelStr {
+ l := strings.Split(label, ":")
+ if len(l) != 2 {
+ return nil, errors.New("wrong query syntax:" + label)
+ }
+ labels[l[0]] = l[1]
+ }
+ if len(labels) == 0 {
+ continue
+ }
+ labelCombinations = append(labelCombinations, labels)
}
- return policy
+ return labelCombinations, nil
}
//WriteErrResponse write error message to client
diff --git a/server/resource/v1/common_test.go b/server/resource/v1/common_test.go
new file mode 100644
index 0000000..6f3b139
--- /dev/null
+++ b/server/resource/v1/common_test.go
@@ -0,0 +1,31 @@
+package v1_test
+
+import (
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+
+ . "github.com/apache/servicecomb-kie/server/resource/v1"
+ "github.com/emicklei/go-restful"
+ "net/http"
+)
+
+var _ = Describe("Common", func() {
+ Describe("set query combination", func() {
+ Context("valid param", func() {
+ r, err := http.NewRequest("GET",
+ "/kv?q=app:mall+service:payment&q=app:mall+service:payment+version:1.0.0",
+ nil)
+ It("should not return err ", func() {
+ Expect(err).Should(BeNil())
+ })
+ c, err := ReadLabelCombinations(restful.NewRequest(r))
+ It("should not return err ", func() {
+ Expect(err).Should(BeNil())
+ })
+ It("should has 2 combinations", func() {
+ Expect(len(c)).Should(Equal(2))
+ })
+
+ })
+ })
+})
diff --git a/server/resource/v1/doc_struct.go b/server/resource/v1/doc_struct.go
index 37f7432..33f0eb7 100644
--- a/server/resource/v1/doc_struct.go
+++ b/server/resource/v1/doc_struct.go
@@ -31,17 +31,19 @@ var (
ParamType: goRestful.HeaderParameterKind,
Desc: "integer, default is 1, if you set match policy, you can set,depth to decide label number",
}
+ DocQueryCombination = &restful.Parameters{
+ DataType: "string",
+ Name: common.QueryParamQ,
+ ParamType: goRestful.QueryParameterKind,
+ Desc: "the combination format is {label_key}:{label_value}+{label_key}:{label_value} " +
+ "for example: /v1/kv?q=app:mall&q=app:mall+service:cart " +
+ "that will query key values from 2 kinds of labels",
+ }
DocPathKey = &restful.Parameters{
DataType: "string",
Name: "key",
ParamType: goRestful.PathParameterKind,
}
- DocHeaderMath = &restful.Parameters{
- DataType: "string",
- Name: common.HeaderMatch,
- ParamType: goRestful.HeaderParameterKind,
- Desc: "greedy or exact",
- }
)
//KVBody is open api doc
diff --git a/server/resource/v1/kv_resource.go b/server/resource/v1/kv_resource.go
index a1f94b6..c072dc6 100644
--- a/server/resource/v1/kv_resource.go
+++ b/server/resource/v1/kv_resource.go
@@ -21,7 +21,6 @@ package v1
import (
"encoding/json"
"fmt"
- "github.com/apache/servicecomb-kie/pkg/common"
"github.com/apache/servicecomb-kie/pkg/model"
"github.com/apache/servicecomb-kie/server/dao"
goRestful "github.com/emicklei/go-restful"
@@ -67,8 +66,8 @@ func (r *KVResource) Put(context *restful.Context) {
}
-//FindWithKey search key by label and key
-func (r *KVResource) FindWithKey(context *restful.Context) {
+//GetByKey search key by label and key
+func (r *KVResource) GetByKey(context *restful.Context) {
var err error
key := context.ReadPathParameter("key")
if key == "" {
@@ -94,23 +93,12 @@ func (r *KVResource) FindWithKey(context *restful.Context) {
WriteErrResponse(context, http.StatusInternalServerError, MsgDomainMustNotBeEmpty)
return
}
- policy := ReadMatchPolicy(context)
d, err := ReadFindDepth(context)
if err != nil {
WriteErrResponse(context, http.StatusBadRequest, MsgIllegalDepth)
return
}
- var kvs []*model.KVResponse
- switch policy {
- case common.MatchGreedy:
- kvs, err = s.FindKV(context.Ctx, domain.(string), dao.WithKey(key), dao.WithLabels(labels), dao.WithDepth(d))
- case common.MatchExact:
- kvs, err = s.FindKV(context.Ctx, domain.(string), dao.WithKey(key), dao.WithLabels(labels),
- dao.WithExactLabels())
- default:
- WriteErrResponse(context, http.StatusBadRequest, MsgIllegalFindPolicy)
- return
- }
+ kvs, err := s.FindKV(context.Ctx, domain.(string), dao.WithKey(key), dao.WithLabels(labels), dao.WithDepth(d))
if err == dao.ErrKeyNotExists {
WriteErrResponse(context, http.StatusNotFound, err.Error())
return
@@ -126,17 +114,13 @@ func (r *KVResource) FindWithKey(context *restful.Context) {
}
-//FindByLabels search key only by label
-func (r *KVResource) FindByLabels(context *restful.Context) {
+//SearchByLabels search key only by label
+func (r *KVResource) SearchByLabels(context *restful.Context) {
var err error
- values := context.ReadRequest().URL.Query()
- labels := make(map[string]string, len(values))
- for k, v := range values {
- if len(v) != 1 {
- WriteErrResponse(context, http.StatusBadRequest, MsgIllegalLabels)
- return
- }
- labels[k] = v[0]
+ labelCombinations, err := ReadLabelCombinations(context.ReadRestfulRequest())
+ if err != nil {
+ WriteErrResponse(context, http.StatusBadRequest, err.Error())
+ return
}
s, err := dao.NewKVService()
if err != nil {
@@ -148,27 +132,24 @@ func (r *KVResource) FindByLabels(context *restful.Context) {
WriteErrResponse(context, http.StatusInternalServerError, MsgDomainMustNotBeEmpty)
return
}
- policy := ReadMatchPolicy(context)
- d, err := ReadFindDepth(context)
- if err != nil {
- WriteErrResponse(context, http.StatusBadRequest, MsgIllegalDepth)
- return
- }
var kvs []*model.KVResponse
- switch policy {
- case common.MatchGreedy:
- kvs, err = s.FindKV(context.Ctx, domain.(string), dao.WithLabels(labels), dao.WithDepth(d))
- case common.MatchExact:
- kvs, err = s.FindKV(context.Ctx, domain.(string), dao.WithLabels(labels),
- dao.WithExactLabels())
- default:
- WriteErrResponse(context, http.StatusBadRequest, MsgIllegalFindPolicy)
- return
+ for _, labels := range labelCombinations {
+ result, err := s.FindKV(context.Ctx, domain.(string), dao.WithLabels(labels))
+ if err != nil {
+ if err == dao.ErrKeyNotExists {
+ continue
+ }
+ WriteErrResponse(context, http.StatusInternalServerError, err.Error())
+ return
+ }
+ kvs = append(kvs, result...)
+
}
- if err == dao.ErrKeyNotExists {
+ if len(kvs) == 0 {
WriteErrResponse(context, http.StatusNotFound, err.Error())
return
}
+
err = context.WriteHeaderAndJSON(http.StatusOK, kvs, goRestful.MIME_JSON)
if err != nil {
openlogging.Error(err.Error())
@@ -215,7 +196,7 @@ func (r *KVResource) URLPatterns() []restful.Route {
DataType: "string",
Name: "X-Realm",
ParamType: goRestful.HeaderParameterKind,
- Desc: "set kv to heterogeneous config server",
+ Desc: "set kv to heterogeneous config server, not implement yet",
},
},
Returns: []*restful.Returns{
@@ -230,7 +211,7 @@ func (r *KVResource) URLPatterns() []restful.Route {
}, {
Method: http.MethodGet,
Path: "/v1/kv/{key}",
- ResourceFuncName: "FindWithKey",
+ ResourceFuncName: "GetByKey",
FuncDesc: "get key values by key and labels",
Parameters: []*restful.Parameters{
DocPathKey, DocHeaderMath, DocHeaderDepth,
@@ -239,7 +220,7 @@ func (r *KVResource) URLPatterns() []restful.Route {
{
Code: http.StatusOK,
Message: "get key value success",
- Model: []*KVBody{},
+ Model: []*model.KVResponse{},
},
},
Consumes: []string{goRestful.MIME_JSON},
@@ -248,16 +229,16 @@ func (r *KVResource) URLPatterns() []restful.Route {
}, {
Method: http.MethodGet,
Path: "/v1/kv",
- ResourceFuncName: "FindByLabels",
- FuncDesc: "find key values only by labels",
+ ResourceFuncName: "SearchByLabels",
+ FuncDesc: "search key values by labels combination",
Parameters: []*restful.Parameters{
- DocHeaderMath, DocHeaderDepth,
+ DocHeaderMath, DocQueryCombination,
},
Returns: []*restful.Returns{
{
Code: http.StatusOK,
Message: "get key value success",
- Model: []*KVBody{},
+ Model: []*model.KVResponse{},
},
},
Consumes: []string{goRestful.MIME_JSON},
diff --git a/server/resource/v1/v1_suite_test.go b/server/resource/v1/v1_suite_test.go
new file mode 100644
index 0000000..23b7482
--- /dev/null
+++ b/server/resource/v1/v1_suite_test.go
@@ -0,0 +1,13 @@
+package v1_test
+
+import (
+ "testing"
+
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+)
+
+func TestV1(t *testing.T) {
+ RegisterFailHandler(Fail)
+ RunSpecs(t, "V1 Suite")
+}