You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ti...@apache.org on 2020/02/07 02:49:47 UTC

[servicecomb-kie] branch master updated: #87 view create and get content (#88)

This is an automated email from the ASF dual-hosted git repository.

tianxiaoliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-kie.git


The following commit(s) were added to refs/heads/master by this push:
     new f1ff3dd  #87  view create and get content (#88)
f1ff3dd is described below

commit f1ff3ddaa784dbff19879a97410fd3c2beddb8b6
Author: Shawn <xi...@gmail.com>
AuthorDate: Fri Feb 7 10:49:37 2020 +0800

    #87  view create and get content (#88)
    
    * #87  view create and get content
    
    * #87  ut
    
    * #87  ut
    
    * #87  ut
    
    * #87  ut
    
    * #87  ut
    
    * #87 lint
    
    * #87 lint
    
    * #87 lint
---
 .travis.yml                                    |   4 +-
 client/client.go                               |   8 +-
 client/client_test.go                          |  25 ++--
 deployments/db.js                              |  23 +++-
 examples/dev/docker-compose.yaml               |   2 +-
 go.mod                                         |   4 +-
 go.sum                                         |  63 +++++++++
 pkg/model/db_schema.go                         |   9 ++
 pkg/model/kv.go                                |   6 +
 server/resource/v1/common.go                   |   1 +
 server/resource/v1/kv_resource.go              |   1 +
 server/resource/v1/label_resouce.go            |   5 +-
 server/service/mongo/kv/kv_test.go             |   4 +-
 server/service/mongo/kv/tool.go                |   6 +-
 server/service/mongo/label/label_dao.go        |   2 +-
 server/service/mongo/label/label_service.go    |   2 +
 server/service/mongo/session/session.go        |  28 +++-
 server/service/mongo/view/view_dao.go          |  58 ++++++++
 server/service/mongo/view/view_service.go      | 177 +++++++++++++++++++++++++
 server/service/mongo/view/view_service_test.go | 113 ++++++++++++++++
 server/service/service.go                      |  16 ++-
 21 files changed, 519 insertions(+), 38 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index f9147ae..a2f7b8a 100755
--- a/.travis.yml
+++ b/.travis.yml
@@ -43,7 +43,7 @@ jobs:
         - bash scripts/travis/goConstChecker.sh
     - stage: GoLint Checker
       script:
-        - go get -u golang.org/x/lint
+        - go get -u golang.org/x/lint/golint
         - bash scripts/travis/goLintChecker.sh
     - stage: GoCyclo Checker
       script:
@@ -55,8 +55,8 @@ jobs:
         - GO111MODULE=on go mod download
         - GO111MODULE=on go mod vendor
         - bash scripts/travis/start_deps.sh
-        - sleep 15
         - cd $HOME/gopath/src/github.com/apache/servicecomb-kie
         - go get github.com/mattn/goveralls
         - go get golang.org/x/tools/cmd/cover
+        - sleep 30
         - bash scripts/travis/unit_test.sh && $HOME/gopath/bin/goveralls -coverprofile=coverage.txt -service=travis-ci
diff --git a/client/client.go b/client/client.go
index 01b8e94..2bc1d43 100644
--- a/client/client.go
+++ b/client/client.go
@@ -53,7 +53,7 @@ type Client struct {
 	opts            Config
 	cipher          security.Cipher
 	c               *httpclient.Requests
-	currentRevision string
+	CurrentRevision string
 }
 
 //Config is the config of client
@@ -133,9 +133,9 @@ func (c *Client) Get(ctx context.Context, opts ...GetOption) (*model.KVResponse,
 
 	var url string
 	if options.Key != "" {
-		url = fmt.Sprintf("%s/%s/%s/%s/%s?revision=%s", c.opts.Endpoint, version, options.Project, APIPathKV, options.Key, c.currentRevision)
+		url = fmt.Sprintf("%s/%s/%s/%s/%s?revision=%s", c.opts.Endpoint, version, options.Project, APIPathKV, options.Key, c.CurrentRevision)
 	} else {
-		url = fmt.Sprintf("%s/%s/%s/%s?revision=%s", c.opts.Endpoint, version, options.Project, APIPathKV, c.currentRevision)
+		url = fmt.Sprintf("%s/%s/%s/%s?revision=%s", c.opts.Endpoint, version, options.Project, APIPathKV, c.CurrentRevision)
 	}
 	if options.Wait != "" {
 		url = url + "&wait=" + options.Wait
@@ -176,7 +176,7 @@ func (c *Client) Get(ctx context.Context, opts ...GetOption) (*model.KVResponse,
 		openlogging.Error("unmarshal kv failed:" + err.Error())
 		return nil, err
 	}
-	c.currentRevision = resp.Header.Get(common.HeaderRevision)
+	c.CurrentRevision = resp.Header.Get(common.HeaderRevision)
 	return kvs, nil
 }
 
diff --git a/client/client_test.go b/client/client_test.go
index 53cc84b..b66a598 100644
--- a/client/client_test.go
+++ b/client/client_test.go
@@ -37,17 +37,17 @@ func TestClient_Put(t *testing.T) {
 		Labels: map[string]string{"service": "client"},
 		Value:  "timeout: 1s",
 	}
-	_, err := c.Put(context.TODO(), kv, WithProject("test"))
+	_, err := c.Put(context.TODO(), kv, WithProject("client_test"))
 	assert.NoError(t, err)
 
 	kvs, _ := c.Get(context.TODO(),
 		WithKey("app.properties"),
-		WithGetProject("test"),
+		WithGetProject("client_test"),
 		WithLabels(map[string]string{"service": "client"}))
 	assert.GreaterOrEqual(t, len(kvs.Data), 1)
 
 	_, err = c.Get(context.TODO(),
-		WithGetProject("test"),
+		WithGetProject("client_test"),
 		WithLabels(map[string]string{"service": "client"}))
 	assert.Equal(t, ErrNoChanges, err)
 
@@ -59,7 +59,7 @@ func TestClient_Put(t *testing.T) {
 		go func() {
 			kvs, err = c.Get(context.TODO(),
 				WithLabels(map[string]string{"service": "client"}),
-				WithGetProject("test"),
+				WithGetProject("client_test"),
 				WithWait("10s"))
 			assert.NoError(t, err)
 			assert.Equal(t, "timeout: 2s", kvs.Data[0].Value)
@@ -69,7 +69,7 @@ func TestClient_Put(t *testing.T) {
 			Labels: map[string]string{"service": "client"},
 			Value:  "timeout: 2s",
 		}
-		_, err := c.Put(context.TODO(), kv, WithProject("test"))
+		_, err := c.Put(context.TODO(), kv, WithProject("client_test"))
 		assert.NoError(t, err)
 	})
 	t.Run("exact match", func(t *testing.T) {
@@ -78,10 +78,11 @@ func TestClient_Put(t *testing.T) {
 			Labels: map[string]string{"service": "client", "version": "1.0"},
 			Value:  "timeout: 2s",
 		}
-		_, err := c.Put(context.TODO(), kv, WithProject("test"))
+		_, err := c.Put(context.TODO(), kv, WithProject("client_test"))
 		assert.NoError(t, err)
+		t.Log(c.CurrentRevision)
 		kvs, err = c.Get(context.TODO(),
-			WithGetProject("test"),
+			WithGetProject("client_test"),
 			WithLabels(map[string]string{"service": "client"}),
 			WithExact())
 		assert.NoError(t, err)
@@ -99,15 +100,15 @@ func TestClient_Delete(t *testing.T) {
 	kvBody.Value = "100s"
 	kvBody.ValueType = "text"
 	kvBody.Labels = make(map[string]string)
-	kvBody.Labels["env"] = "test"
-	kv, err := c.Put(context.TODO(), kvBody, WithProject("test"))
+	kvBody.Labels["env"] = "client_test"
+	kv, err := c.Put(context.TODO(), kvBody, WithProject("client_test"))
 	assert.NoError(t, err)
 	kvs, err := c.Get(context.TODO(),
 		WithKey("time"),
-		WithGetProject("test"),
-		WithLabels(map[string]string{"env": "test"}))
+		WithGetProject("client_test"),
+		WithLabels(map[string]string{"env": "client_test"}))
 	assert.NoError(t, err)
 	assert.NotNil(t, kvs)
-	err = c.Delete(context.TODO(), kv.ID, "", WithProject("test"))
+	err = c.Delete(context.TODO(), kv.ID, "", WithProject("client_test"))
 	assert.NoError(t, err)
 }
diff --git a/deployments/db.js b/deployments/db.js
index 288b2d9..ef6e407 100644
--- a/deployments/db.js
+++ b/deployments/db.js
@@ -67,11 +67,32 @@ db.createCollection( "label", {
             }
         } }
 } );
-
+db.createCollection( "view", {
+    validator: { $jsonSchema: {
+            bsonType: "object",
+            required: [ "id","domain","project","display","criteria" ],
+            properties: {
+                id: {
+                    bsonType: "string",
+                },
+                domain: {
+                    bsonType: "string"
+                },
+                project: {
+                    bsonType: "string"
+                },
+                criteria: {
+                    bsonType: "string"
+                }
+            }
+        } }
+} );
 //index
 db.kv.createIndex({"id": 1}, { unique: true } );
 db.kv.createIndex({key: 1, label_id: 1,domain:1,project:1},{ unique: true });
 db.label.createIndex({"id": 1}, { unique: true } );
 db.label.createIndex({format: 1,domain:1,project:1},{ unique: true });
+db.view.createIndex({"id": 1}, { unique: true } );
+db.view.createIndex({display:1,domain:1,project:1},{ unique: true });
 //db config
 db.setProfilingLevel(1, {slowms: 80, sampleRate: 1} );
\ No newline at end of file
diff --git a/examples/dev/docker-compose.yaml b/examples/dev/docker-compose.yaml
index 8ca81b4..04e207d 100644
--- a/examples/dev/docker-compose.yaml
+++ b/examples/dev/docker-compose.yaml
@@ -17,7 +17,7 @@
 version: '3.1'
 services:
   mongo:
-    image: mongo
+    image: mongo:4.0
     restart: always
     ports:
       - 27017:27017
diff --git a/go.mod b/go.mod
index 70eda61..4c0ea9e 100644
--- a/go.mod
+++ b/go.mod
@@ -8,15 +8,13 @@ require (
 	github.com/go-chassis/go-chassis v1.8.2-0.20191227102336-e3ac2ea137b1
 	github.com/go-chassis/paas-lager v1.1.1
 	github.com/go-mesh/openlogging v1.0.1
-	github.com/golang/snappy v0.0.1 // indirect
 	github.com/hashicorp/mdns v1.0.1 // indirect
 	github.com/hashicorp/serf v0.8.5
 	github.com/satori/go.uuid v1.2.0
 	github.com/stretchr/testify v1.4.0
 	github.com/urfave/cli v1.20.0
-	github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c // indirect
 	github.com/xdg/stringprep v1.0.0 // indirect
-	go.mongodb.org/mongo-driver v1.2.1
+	go.mongodb.org/mongo-driver v1.3.0
 	gopkg.in/yaml.v2 v2.2.4
 )
 
diff --git a/go.sum b/go.sum
index a13f0fb..255818c 100644
--- a/go.sum
+++ b/go.sum
@@ -73,6 +73,30 @@ github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nA
 github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
 github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
+github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
+github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg=
+github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
+github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
+github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs=
+github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
+github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
+github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk=
+github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28=
+github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo=
+github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk=
+github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw=
+github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360=
+github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg=
+github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE=
+github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8=
+github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
+github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
+github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
+github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
+github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
+github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
+github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
 github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@@ -136,6 +160,8 @@ github.com/hashicorp/serf v0.8.5/go.mod h1:UpNcs7fFbpKIyZaUuSW6EPiH+eZC7OuyFD+wc
 github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
+github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
+github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
 github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok=
@@ -143,14 +169,21 @@ github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u
 github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
+github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
 github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/compress v1.9.5 h1:U+CaK85mrNNb4k8BNOfgJtJ/gr6kswUCFj6miSzVC6M=
+github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
+github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
 github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
 github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
 github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI=
@@ -170,6 +203,7 @@ github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lN
 github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
 github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
 github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
@@ -185,9 +219,12 @@ github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFSt
 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
 github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
 github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
+github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
 github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
 github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -203,19 +240,27 @@ github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
 github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
 github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1 h1:/K3IL0Z1quvmJ7X0A1AwNEK7CRkVK3YwfOU/QAL4WGg=
 github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
 github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
 github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
+github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
 github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
 github.com/spf13/cast v1.2.0 h1:HHl1DSRbEQN2i8tJmtS6ViPyHx35+p51amrdsiTCrkg=
 github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
+github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
 github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -224,21 +269,27 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
 github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
 github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
 github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c h1:u40Z8hqBAAQyv+vATcGgV0YCnDjqSL7/q/JyPhhJSPk=
 github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
+github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
 github.com/xdg/stringprep v1.0.0 h1:d9X0esnoa3dFsV0FG35rAT0RIhYFlPq7MiP+DW89La0=
 github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
 go.mongodb.org/mongo-driver v1.0.3 h1:GKoji1ld3tw2aC+GX1wbr/J2fX13yNacEYoJ8Nhr0yU=
 go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
 go.mongodb.org/mongo-driver v1.2.1 h1:ANAlYXXM5XmOdW/Nc38jOr+wS5nlk7YihT24U1imiWM=
 go.mongodb.org/mongo-driver v1.2.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
+go.mongodb.org/mongo-driver v1.3.0 h1:ew6uUIeJOo+qdUUv7LxFCUhtWmVv7ZV/Xuy4FAUsw2E=
+go.mongodb.org/mongo-driver v1.3.0/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE=
 go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
+golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 h1:7KByu05hhLed2MO29w7p1XfZvZ13m8mub3shuVftRs0=
 golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -266,6 +317,9 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI=
 golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -275,7 +329,11 @@ golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5h
 golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191018095205-727590c5006e h1:ZtoklVMHQy6BFRHkbG6JzK+S6rX82//Yeok1vMlizfQ=
 golang.org/x/sys v0.0.0-20191018095205-727590c5006e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -294,6 +352,10 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm
 golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
 golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -305,6 +367,7 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
 gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
 gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
diff --git a/pkg/model/db_schema.go b/pkg/model/db_schema.go
index 535e495..19922f4 100644
--- a/pkg/model/db_schema.go
+++ b/pkg/model/db_schema.go
@@ -43,3 +43,12 @@ type KVDoc struct {
 	Domain string            `json:"domain,omitempty" yaml:"domain,omitempty"` //redundant
 
 }
+
+//ViewDoc is db struct, it saves user's custom view name and criteria
+type ViewDoc struct {
+	ID       string `json:"id,omitempty" bson:"id,omitempty" yaml:"id,omitempty" swag:"string"`
+	Display  string `json:"display,omitempty" yaml:"display,omitempty"`
+	Project  string `json:"project,omitempty" yaml:"project,omitempty"`
+	Domain   string `json:"domain,omitempty" yaml:"domain,omitempty"`
+	Criteria string `json:"criteria,omitempty" yaml:"criteria,omitempty"`
+}
diff --git a/pkg/model/kv.go b/pkg/model/kv.go
index a9a8952..0db6875 100644
--- a/pkg/model/kv.go
+++ b/pkg/model/kv.go
@@ -48,3 +48,9 @@ type LabelHistoryResponse struct {
 	KVs      []*KVDoc          `json:"data,omitempty"`
 	Revision int               `json:"revision"`
 }
+
+//ViewResponse represents the view list
+type ViewResponse struct {
+	Total int        `json:"total,omitempty"`
+	Data  []*ViewDoc `json:"data,omitempty"`
+}
diff --git a/server/resource/v1/common.go b/server/resource/v1/common.go
index 310b4e3..3414554 100644
--- a/server/resource/v1/common.go
+++ b/server/resource/v1/common.go
@@ -50,6 +50,7 @@ const (
 	MaxWait = 5 * time.Minute
 )
 
+//err
 var (
 	ErrInvalidRev = errors.New(MsgInvalidRev)
 )
diff --git a/server/resource/v1/kv_resource.go b/server/resource/v1/kv_resource.go
index 8851f5e..87ba64b 100644
--- a/server/resource/v1/kv_resource.go
+++ b/server/resource/v1/kv_resource.go
@@ -106,6 +106,7 @@ func (r *KVResource) GetByKey(rctx *restful.Context) {
 	returnData(rctx, domain, project, labels, limit, offset)
 }
 
+//List response kv list
 func (r *KVResource) List(rctx *restful.Context) {
 	var err error
 	project := rctx.ReadPathParameter("project")
diff --git a/server/resource/v1/label_resouce.go b/server/resource/v1/label_resouce.go
index a29a865..c573189 100644
--- a/server/resource/v1/label_resouce.go
+++ b/server/resource/v1/label_resouce.go
@@ -10,12 +10,11 @@ import (
 	"net/http"
 )
 
-//LabelResource
+//LabelResource is label API
 type LabelResource struct {
 }
 
-//PutLabel
-// update by label_id , only can modify alias
+//PutLabel update by label_id , only can modify alias
 // create return 201 / update return 200
 func (r *LabelResource) PutLabel(context *restful.Context) {
 	var err error
diff --git a/server/service/mongo/kv/kv_test.go b/server/service/mongo/kv/kv_test.go
index 0416053..69afb3a 100644
--- a/server/service/mongo/kv/kv_test.go
+++ b/server/service/mongo/kv/kv_test.go
@@ -97,12 +97,12 @@ func TestService_CreateOrUpdate(t *testing.T) {
 			Domain:  "default",
 			Project: "test",
 		})
-		assert.Equal(t, beforeKV.ID, afterKV.ID)
+		assert.Equal(t, "3s", afterKV.Value)
 		savedKV, err := kvsvc.Exist(context.Background(), "default", "timeout", "test", service.WithLabels(map[string]string{
 			"app": "mall",
 		}))
 		assert.NoError(t, err)
-		assert.Equal(t, beforeKV.ID, savedKV.ID)
+		assert.Equal(t, afterKV.Value, savedKV.Value)
 		kvs, err := kvsvc.FindKV(context.Background(), "default", "test",
 			service.WithKey("timeout"),
 			service.WithLabels(map[string]string{
diff --git a/server/service/mongo/kv/tool.go b/server/service/mongo/kv/tool.go
index c1a3f47..6852cfe 100644
--- a/server/service/mongo/kv/tool.go
+++ b/server/service/mongo/kv/tool.go
@@ -20,6 +20,7 @@ package kv
 import (
 	"context"
 	"github.com/apache/servicecomb-kie/server/service"
+	"reflect"
 
 	"github.com/apache/servicecomb-kie/pkg/model"
 	"github.com/go-mesh/openlogging"
@@ -38,19 +39,18 @@ func clearPart(kv *model.KVDoc) {
 }
 func cursorToOneKV(ctx context.Context, cur *mongo.Cursor, labels map[string]string) ([]*model.KVResponse, error) {
 	result := make([]*model.KVResponse, 0)
-	curKV := &model.KVDoc{} //reuse this pointer to reduce GC, only clear label
 	//check label length to get the exact match
 	for cur.Next(ctx) { //although complexity is O(n), but there won't be so much labels for one key
 		if cur.Err() != nil {
 			return nil, cur.Err()
 		}
-		curKV.Labels = nil
+		curKV := &model.KVDoc{}
 		err := cur.Decode(curKV)
 		if err != nil {
 			openlogging.Error("decode error: " + err.Error())
 			return nil, err
 		}
-		if len(curKV.Labels) == len(labels) {
+		if reflect.DeepEqual(curKV.Labels, labels) {
 			openlogging.Debug("hit exact labels")
 			labelGroup := &model.KVResponse{
 				LabelDoc: &model.LabelDocResponse{
diff --git a/server/service/mongo/label/label_dao.go b/server/service/mongo/label/label_dao.go
index 5a75283..5fb14aa 100644
--- a/server/service/mongo/label/label_dao.go
+++ b/server/service/mongo/label/label_dao.go
@@ -97,7 +97,7 @@ func CreateLabel(ctx context.Context, label *model.LabelDoc) (*model.LabelDoc, e
 	return label, nil
 }
 
-//UpdateLabel
+//UpdateLabel update alias
 func UpdateLabel(ctx context.Context, label *model.LabelDoc) (*model.LabelDoc, error) {
 	collection := session.GetDB().Collection(session.CollectionLabel)
 	queryFilter := bson.M{"id": label.ID}
diff --git a/server/service/mongo/label/label_service.go b/server/service/mongo/label/label_service.go
index 1ae2904..5b0d934 100644
--- a/server/service/mongo/label/label_service.go
+++ b/server/service/mongo/label/label_service.go
@@ -5,9 +5,11 @@ import (
 	"github.com/apache/servicecomb-kie/pkg/model"
 )
 
+//Service is db service
 type Service struct {
 }
 
+//CreateOrUpdate create or update labels
 func (s *Service) CreateOrUpdate(ctx context.Context, label *model.LabelDoc) (*model.LabelDoc, error) {
 	if label.ID != "" {
 		return UpdateLabel(ctx, label)
diff --git a/server/service/mongo/session/session.go b/server/service/mongo/session/session.go
index 58f9289..199a8bf 100644
--- a/server/service/mongo/session/session.go
+++ b/server/service/mongo/session/session.go
@@ -46,9 +46,9 @@ const (
 	CollectionKV         = "kv"
 	CollectionKVRevision = "kv_revision"
 	CollectionCounter    = "counter"
-
-	DefaultTimeout   = 5 * time.Second
-	DefaultValueType = "text"
+	CollectionView       = "view"
+	DefaultTimeout       = 5 * time.Second
+	DefaultValueType     = "text"
 )
 
 //db errors
@@ -59,9 +59,14 @@ var (
 	ErrTooMany         = errors.New("key with labels should be only one")
 	ErrKeyMustNotEmpty = errors.New("must supply key if you want to get exact one result")
 
-	ErrKVIDIsNil              = errors.New("kvID id is nil")
+	ErrIDIsNil                = errors.New("id is empty")
 	ErrKvIDAndLabelIDNotMatch = errors.New("kvID and labelID do not match")
 	ErrRootCAMissing          = errors.New("rootCAFile is empty in config file")
+
+	ErrViewCreation = errors.New("can not create view")
+	ErrViewUpdate   = errors.New("can not update view")
+	ErrViewNotExist = errors.New("view not exists")
+	ErrViewFinding  = errors.New("view search error")
 )
 
 var client *mongo.Client
@@ -132,3 +137,18 @@ func Init() error {
 func GetDB() *mongo.Database {
 	return db
 }
+
+//CreateView run mongo db command to create view
+func CreateView(ctx context.Context, view, source string, pipeline mongo.Pipeline) error {
+	sr := GetDB().RunCommand(ctx,
+		bson.D{
+			{"create", view},
+			{"viewOn", source},
+			{"pipeline", pipeline},
+		})
+	if sr.Err() != nil {
+		openlogging.Error("can not create view: " + sr.Err().Error())
+		return ErrViewCreation
+	}
+	return nil
+}
diff --git a/server/service/mongo/view/view_dao.go b/server/service/mongo/view/view_dao.go
new file mode 100644
index 0000000..90d4314
--- /dev/null
+++ b/server/service/mongo/view/view_dao.go
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package view
+
+import (
+	"context"
+	"github.com/apache/servicecomb-kie/pkg/model"
+	"github.com/apache/servicecomb-kie/server/service/mongo/session"
+	"github.com/go-mesh/openlogging"
+	uuid "github.com/satori/go.uuid"
+	"go.mongodb.org/mongo-driver/bson"
+)
+
+func create(ctx context.Context, viewDoc *model.ViewDoc) error {
+	viewDoc.ID = uuid.NewV4().String()
+	viewDoc.Criteria = "" //TODO parse pipe line to sql-like lang
+	_, err := session.GetDB().Collection(session.CollectionView).InsertOne(ctx, viewDoc)
+	if err != nil {
+		openlogging.Error("can not insert view collection: " + err.Error())
+		return session.ErrViewCreation
+	}
+	return nil
+}
+func findOne(ctx context.Context, viewID, domain, project string) (*model.ViewDoc, error) {
+	filter := bson.M{"domain": domain,
+		"project": project,
+		"id":      viewID}
+	sr := session.GetDB().Collection(session.CollectionView).FindOne(ctx, filter)
+	if sr.Err() != nil {
+		openlogging.Error("can not insert view collection: " + sr.Err().Error())
+		return nil, sr.Err()
+	}
+	result := &model.ViewDoc{}
+	err := sr.Decode(result)
+	if err != nil {
+		openlogging.Error("decode error: " + err.Error())
+		return nil, err
+	}
+	if result.ID == viewID {
+		return result, nil
+	}
+	return nil, session.ErrViewNotExist
+}
diff --git a/server/service/mongo/view/view_service.go b/server/service/mongo/view/view_service.go
new file mode 100644
index 0000000..98c9f9b
--- /dev/null
+++ b/server/service/mongo/view/view_service.go
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package view
+
+import (
+	"context"
+	"github.com/apache/servicecomb-kie/pkg/model"
+	"github.com/apache/servicecomb-kie/server/service"
+	"github.com/apache/servicecomb-kie/server/service/mongo/session"
+	"github.com/go-mesh/openlogging"
+	uuid "github.com/satori/go.uuid"
+	"go.mongodb.org/mongo-driver/bson"
+	"go.mongodb.org/mongo-driver/mongo"
+	"go.mongodb.org/mongo-driver/mongo/options"
+	"time"
+)
+
+//Service operate data in mongodb
+type Service struct {
+	timeout time.Duration
+}
+
+//Create insert a view data and create a mongo db view
+func (s *Service) Create(ctx context.Context, viewDoc *model.ViewDoc, options ...service.FindOption) (*model.ViewDoc, error) {
+	if viewDoc.Domain == "" {
+		return nil, session.ErrMissingDomain
+	}
+	var pipeline mongo.Pipeline = []bson.D{
+		{{"$match", bson.D{{"domain", viewDoc.Domain}}}},
+		{{"$match", bson.D{{"project", viewDoc.Project}}}},
+	}
+	opts := service.FindOptions{}
+	for _, o := range options {
+		o(&opts)
+	}
+	if opts.Key != "" {
+		pipeline = append(pipeline, bson.D{{"$match", bson.D{{"key", opts.Key}}}})
+	}
+	if len(opts.Labels) != 0 {
+		for k, v := range opts.Labels {
+			pipeline = append(pipeline, bson.D{{"$match", bson.D{{"labels." + k, v}}}})
+		}
+	}
+	viewDoc.ID = uuid.NewV4().String()
+	viewDoc.Criteria = "" //TODO parse pipe line to sql-like lang
+	err := create(ctx, viewDoc)
+	if err != nil {
+		openlogging.Error("can not insert view collection: " + err.Error())
+		return nil, session.ErrViewCreation
+	}
+	err = session.CreateView(ctx, generateViewName(viewDoc.ID, viewDoc.Domain, viewDoc.Project), session.CollectionKV, pipeline)
+	if err != nil {
+		openlogging.Error("can not create view: " + err.Error())
+		return nil, session.ErrViewCreation
+	}
+	return viewDoc, nil
+}
+
+//Update is only able to update name and criteria
+func (s *Service) Update(ctx context.Context, viewDoc *model.ViewDoc) error {
+	if viewDoc.Domain == "" {
+		return session.ErrMissingDomain
+	}
+	if viewDoc.Project == "" {
+		return session.ErrMissingProject
+	}
+	if viewDoc.ID == "" {
+		return session.ErrIDIsNil
+	}
+	oldView, err := findOne(ctx, viewDoc.ID, viewDoc.Domain, viewDoc.Project)
+	if err != nil {
+		return err
+	}
+	if viewDoc.Display != "" {
+		oldView.Display = viewDoc.Display
+	}
+	if viewDoc.Criteria != "" {
+		oldView.Criteria = viewDoc.Criteria
+	}
+	_, err = session.GetDB().Collection(session.CollectionView).UpdateOne(ctx, bson.M{"domain": oldView.Domain,
+		"project": oldView.Project,
+		"id":      oldView.ID},
+		bson.D{
+			{"$set", bson.D{
+				{"name", oldView.Display},
+				{"criteria", oldView.Criteria},
+			}},
+		})
+	if err != nil {
+		openlogging.Error("can not update view: " + err.Error())
+		return session.ErrViewUpdate
+	}
+	//TODO delete and create a new view
+	return nil
+}
+
+//List return all view user created
+func (s *Service) List(ctx context.Context, domain, project string, opts ...service.FindOption) (*model.ViewResponse, error) {
+	option := service.FindOptions{}
+	for _, o := range opts {
+		o(&option)
+	}
+	collection := session.GetDB().Collection(session.CollectionView)
+	filter := bson.M{"domain": domain, "project": project}
+	mOpt := options.Find()
+	if option.Limit != 0 {
+		mOpt = mOpt.SetLimit(option.Limit)
+	}
+	if option.Offset != 0 {
+		mOpt = mOpt.SetSkip(option.Offset)
+	}
+	cur, err := collection.Find(ctx, filter, mOpt)
+	if err != nil {
+		openlogging.Error("can not find view: " + err.Error())
+		return nil, session.ErrViewFinding
+	}
+	result := &model.ViewResponse{}
+	for cur.Next(ctx) {
+		v := &model.ViewDoc{}
+		if err := cur.Decode(v); err != nil {
+			openlogging.Error("decode error: " + err.Error())
+			return nil, err
+		}
+		result.Data = append(result.Data, v)
+	}
+	return result, nil
+}
+
+//GetContent query view's kv data
+func (s *Service) GetContent(ctx context.Context, id, domain, project string, opts ...service.FindOption) (*model.KVResponse, error) {
+	option := service.FindOptions{}
+	for _, o := range opts {
+		o(&option)
+	}
+	mOpt := options.Find()
+	if option.Limit != 0 {
+		mOpt = mOpt.SetLimit(option.Limit)
+	}
+	if option.Offset != 0 {
+		mOpt = mOpt.SetSkip(option.Offset)
+	}
+	collection := session.GetDB().Collection(generateViewName(id, domain, project))
+	cur, err := collection.Find(ctx, bson.D{}, mOpt)
+	if err != nil {
+		openlogging.Error("can not find view content: " + err.Error())
+		return nil, session.ErrViewFinding
+	}
+	result := &model.KVResponse{}
+	for cur.Next(ctx) {
+		v := &model.KVDoc{}
+		if err := cur.Decode(v); err != nil {
+			openlogging.Error("decode error: " + err.Error())
+			return nil, err
+		}
+		result.Data = append(result.Data, v)
+	}
+	return result, nil
+}
+
+func generateViewName(id, domain, project string) string {
+	return domain + "::" + project + "::" + id
+}
diff --git a/server/service/mongo/view/view_service_test.go b/server/service/mongo/view/view_service_test.go
new file mode 100644
index 0000000..58d5937
--- /dev/null
+++ b/server/service/mongo/view/view_service_test.go
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package view_test
+
+import (
+	"context"
+	"github.com/apache/servicecomb-kie/pkg/model"
+	"github.com/apache/servicecomb-kie/server/config"
+	"github.com/apache/servicecomb-kie/server/service"
+	"github.com/apache/servicecomb-kie/server/service/mongo/kv"
+	"github.com/apache/servicecomb-kie/server/service/mongo/session"
+	"github.com/apache/servicecomb-kie/server/service/mongo/view"
+	"github.com/stretchr/testify/assert"
+	"testing"
+)
+
+func TestGet(t *testing.T) {
+	var err error
+	config.Configurations = &config.Config{DB: config.DB{URI: "mongodb://kie:123@127.0.0.1:27017/kie"}}
+	err = session.Init()
+	assert.NoError(t, err)
+	kvsvc := &kv.Service{}
+	t.Run("put view data", func(t *testing.T) {
+		kv, err := kvsvc.CreateOrUpdate(context.TODO(), &model.KVDoc{
+			Key:   "timeout",
+			Value: "2s",
+			Labels: map[string]string{
+				"app":     "mall",
+				"service": "cart",
+				"view":    "view_test",
+			},
+			Domain:  "default",
+			Project: "view_test",
+		})
+		assert.NoError(t, err)
+		assert.NotEmpty(t, kv.ID)
+
+		kv, err = kvsvc.CreateOrUpdate(context.TODO(), &model.KVDoc{
+			Key:   "timeout",
+			Value: "2s",
+			Labels: map[string]string{
+				"app": "mall",
+			},
+			Domain:  "default",
+			Project: "view_test",
+		})
+		assert.NoError(t, err)
+		assert.NotEmpty(t, kv.ID)
+
+		kv, err = kvsvc.CreateOrUpdate(context.TODO(), &model.KVDoc{
+			Key:   "retry",
+			Value: "2",
+			Labels: map[string]string{
+				"app": "mall",
+			},
+			Domain:  "default",
+			Project: "view_test",
+		})
+		assert.NoError(t, err)
+		assert.NotEmpty(t, kv.ID)
+	})
+
+	svc := &view.Service{}
+	t.Run("create and get view content", func(t *testing.T) {
+		view1, err := svc.Create(context.TODO(), &model.ViewDoc{
+			Display: "timeout_config",
+			Project: "view_test",
+			Domain:  "default",
+		}, service.WithKey("timeout"))
+		assert.NoError(t, err)
+		assert.NotEmpty(t, view1.ID)
+		view2, err := svc.Create(context.TODO(), &model.ViewDoc{
+			Display: "mall_config",
+			Project: "view_test",
+			Domain:  "default",
+		}, service.WithLabels(map[string]string{
+			"app": "mall",
+		}))
+		assert.NoError(t, err)
+		assert.NotEmpty(t, view2.ID)
+
+		resp1, err := svc.GetContent(context.TODO(), view1.ID, "default", "view_test")
+		assert.NoError(t, err)
+		assert.Equal(t, 2, len(resp1.Data))
+		assert.Equal(t, "timeout", resp1.Data[0].Key)
+
+		resp2, err := svc.GetContent(context.TODO(), view2.ID, "default", "view_test")
+		assert.NoError(t, err)
+		assert.Equal(t, "mall", resp1.Data[0].Labels["app"])
+		t.Log(resp2.Data)
+	})
+	t.Run(" list view", func(t *testing.T) {
+		r, err := svc.List(context.TODO(), "default", "view_test")
+		assert.NoError(t, err)
+		assert.Equal(t, 2, len(r.Data))
+	})
+
+}
diff --git a/server/service/service.go b/server/service/service.go
index 60945f3..a26e697 100644
--- a/server/service/service.go
+++ b/server/service/service.go
@@ -28,13 +28,13 @@ var (
 	KVService       KV
 	HistoryService  History
 	RevisionService Revision
-	DBInit          Init
 	LabelService    Label
+	DBInit          Init
 )
 
 //db errors
 var (
-	ErrKeyNotExists     = errors.New("key with labels does not exits")
+	ErrKeyNotExists     = errors.New("can not find any key value")
 	ErrRevisionNotExist = errors.New("revision does not exist")
 	ErrAliasNotGiven    = errors.New("label alias not given")
 )
@@ -53,13 +53,25 @@ type KV interface {
 type History interface {
 	GetHistory(ctx context.Context, keyID string, options ...FindOption) ([]*model.KVDoc, error)
 }
+
+//Revision is global revision number management
 type Revision interface {
 	GetRevision(ctx context.Context, domain string) (int64, error)
 }
 
+//Label manages labels data
 type Label interface {
 	CreateOrUpdate(ctx context.Context, label *model.LabelDoc) (*model.LabelDoc, error)
 }
 
+//View create update and get view data
+type View interface {
+	Create(ctx context.Context, viewDoc *model.ViewDoc, options ...FindOption) error
+	Update(ctx context.Context, viewDoc *model.ViewDoc) error
+	//TODO
+	//List(ctx context.Context, domain, project string, options ...FindOption) ([]*model.ViewDoc, error)
+	GetContent(ctx context.Context, id, domain, project string, options ...FindOption) ([]*model.KVResponse, error)
+}
+
 //Init init db session
 type Init func() error