1. 什么是Patch?

Patch方法可以用来更新资源的一个组成部分

  1. 什么时候使用Patch?

当你仅需更新资源的某一项,即不完全也不幂等

那当我们的模型在数据库中几乎每个字段都可能会遇到改变的时候,难道在patch的时候,或者专门写一个post的接口去一个一个if else操作吗,而我们又使用的是静态语言golang,有没有什么办法能够动态的让我们进行愉快的Patch呢?

答案当然是有的,先说说如何去实现:

  1. 我们需要利用golang的map[string]interface{}结构

    • 我们需要一个动态的结构

    • 在mgo中大多使用map[string]interface{}的结构,我们直接构造出这个结构有利于我们直接进行Update({"$set": xxxx})操作

  2. 使用BindJSON函数,当然你也可以使用Gin的其他函数对map[string]interface{}进行绑定,这里我们不使用一个struct进行绑定,原因是我们无法判断客户端,或者说是浏览器会传送哪些字段来,这样做也有利于我们客户端将某一个字段置为默认值(如果用struct就只能避开默认值了)

来,开始贴代码:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141

// 这个是我们需要存到数据库中的Model

type Article struct {

	ID          bson.ObjectId `json:"id" bson:"_id" show:"id"`

	Author      string        `json:"author" bson:"author" show:"author"`

	Title       string        `json:"title" bson:"title" show:"title"`

	Content     string        `json:"content" bson:"content" show:"content"`

	Publish     int           `json:"publish" bson:"publish"`

	CreatedTime int64         `json:"created_time" bson:"created_time" show:"created_time"`

	ChangedTime int64         `json:"changed_time" bson:"changed_time" show:"changed_time"`

	PageView    int64         `json:"page_view" bson:"page_view" show:"page_view"` // 浏览量

	ArticleType string        `json:"article_type" bson:"article_type" show:"article_type"`

	ArticleTags []string      `json:"article_tags" bson:"article_tags" show:"article_tags"`

	Deleted     int           `json:"deleted" bson:"deleted"`

}



func ArticlePatch(c *gin.Context) {

	id := c.Query("id")

	if !bson.IsObjectIdHex(id) {

		err_msg := "参数错误"

		resp.SendFailJSON(c, err_msg)

		return

	}

	_id := bson.ObjectIdHex(id)

	if !CheckOwner(c) {

		err_msg := "您没有权限"

		resp.SendFailJSON(c, err_msg)

		return

	}

	mongo := model.GetModel(model.MongoArticleCollection)

	if mongo == nil {

		err_msg := "网络错误"

		resp.SendFailJSON(c, err_msg)

		return

	}

	article := &model.Article{}

	tags := common.GetAllTagValue(article, "json")

	query := bson.M{"_id": _id, "deleted": model.ModelNotDeleted}

	if !mongo.FindOne(article, query) {

		err_msg := "文章不存在"

		resp.SendFailJSON(c, err_msg)

		return

	}

	patchMap := map[string]interface{}{}

	err := c.BindJSON(&patchMap)

	if err != nil {

		err_msg := fmt.Sprint(err)

		resp.SendFailJSON(c, err_msg)

		return

	}

	deleteArray := []string{}

	for k, _ := range patchMap {

		ok, _ := common.InArray(k, tags)

		if !ok {

			deleteArray = append(deleteArray, k)

		}

	}

	deleteCount := len(deleteArray)

	fmt.Println("delete", deleteArray)

	for i := 0; i < deleteCount; i++ {

		delete(patchMap, deleteArray[i])

	}

	fmt.Println(patchMap)

	if !mongo.UpdateOne(query, bson.M{"$set": patchMap}) {

		err_msg := "更新失败"

		resp.SendFailJSON(c, err_msg)

		return

	}

	resp.SendSuccessJSON(c, "更新成功")

}