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 <xiaoliang.t...@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")
+}

Reply via email to