golang+mongodb构建一个博客的API服务

golang+mongodb构建一个博客的API服务

一、简介

这次作业的要求如下:

利用 web 客户端调用远端服务是服务开发本实验的重要内容。其中,要点建立 API First 的开发理念,实现前后端分离,使得团队协作变得更有效率。

因此,需要搭建一个后端服务器,并实现博客相关的API设计。这是一个小组项目,我负责的是博客中comment、like的全部功能。

二、配置相关

本次作业数据库用的是mongodb,后端用的语言是go,web框架用的是gin。gin是一个微框架,运行速度快、支持分组路由、支持错误处理、并提供中间件支持。在gin的安装过程中,由于有许多相应的依赖,最好先确认go的版本大于1.13,并通过如下命令开启代理,再进行安装。

$ go env -w GO111MODULE=on
$ go env -w GOPROXY=https://goproxy.cn,direct

为了让go操作mongodb,还需要引入一个第三方包mgo。
服务器相关的安装在这篇博客中有对应的链接。

三、实现api中的功能

为了使博客能够进行点赞和评论,需要构建对应的API使得前端能够根据相应的API发起请求并获取数据。

构建路由如下:
在这里插入图片描述
注意到,使用了gin框架中的分组路由,这样可以很方便的将相关的操作划分成一组.
定义点赞和评论在数据库的存储格式:

type Comment struct {
	Cid string   `bson:"_id"`
	Content string `bson:"content"`//评论内容
	Publisher string `bson:"publisher"`//评论者用户名
	Id string `bson:"id"` //评论的(文章或评论)的ID
}
type Like struct {
	Lid string   `bson:"_id"`
	Liker string `bson:"liker"`//点赞者用户名
	Id string `bson:"id"` //点赞的(文章或评论)的ID
}

接下来选取几个具体的例子进行讲解.首先是发表评论:
根据上面的评论的数据结构可知,一个评论在数据库存储时,需要包含一个Cid,评论内容,评论者的用户名,评论的文章或评论的ID(因为不仅可能需要给文章评论还可能需要给评论进行评论).由于Cid可以在插入数据库时生成,因此前端只需提供后三个参数即可.
在这里插入图片描述
后端先定义一个所需数据的结构体,并通过json解码即可获得前端传过来的参数.

type Comment_notPublished struct {
	Content string `bson:"content"`//评论内容
	Publisher string `bson:"publisher"`//评论者用户名
	Id string `bson:"id"` //评论的(文章或评论)的ID
}
var comment Comment_notPublished
json.NewDecoder(c.Request.Body).Decode(&comment)

判断用户是否存在:

MyuserModel.DB.Find(bson.M{"username": comment.Publisher}).One(&tmpUser)
hexid := fmt.Sprintf("%x", string(tmpUser.Id))
if (hexid == "") {
	c.JSON(http.StatusOK, &ApiResponse {
		Code: 400,
		Type: "fail",
		Message:  "publisher does not exist",
	})
	return 
}

判断要评论的文章或评论是否存在,若存在则将评论内容插入评论的数据表中.

var articles []Article
var comments []Comment
MyarticleModel.DB.Find(bson.M{"_id": bson.ObjectIdHex(comment.Id)}).All(&articles)
MycommentModel.DB.Find(bson.M{"_id": bson.ObjectIdHex(comment.Id)}).All(&comments)
if len(articles) == 0 && len(comments) == 0 {
	c.JSON(http.StatusOK, &ApiResponse {
		Code: 400,
		Type: "fail",
		Message:  "The contentID does not exist",
	})
}else {
	MycommentModel.DB.Insert(&comment)
	c.JSON(http.StatusOK, &ApiResponse {
		Code: 200,
		Type: "success",
		Message:  "",
	})
}

删除评论,由于可以对文章进行评论,也可以对文章的评论进行评论,也可以对文章的评论的评论进行评论…同时点赞可以对任意文章和评论进行点赞,因此一篇文章及其评论是一颗以文章为根节点的多叉树,因此在删除对应的文章或评论时,需要将其所有子节点全部删除.即需要先遍历该节点下的所有节点,遍历完后依次将其删除.首先根据前端传来的评论或文章的id查找所有的评论,再根据广度优先搜索一层一层的往下遍历,最后将所有子节点放入一个切片中,再执行删除操作.
相关代码:

func GetCommentsByid (id string) []string {
	var comments []Comment
	var commentsid []string
	MycommentModel.DB.Find(bson.M{"id": id}).All(&comments)
	for i,comment := range comments {
		comments[i].Cid = fmt.Sprintf("%x", string(comment.Cid))
		commentsid = append(commentsid, comments[i].Cid)
	}
	return commentsid
}
func GetAllSonComments (id string) []string{
	var arrstr []string
	var res []string
	arrstr = append(arrstr, id)
	i := 0
	res = append(res, id)
	for ; i < len(arrstr); i++ {
		res = append(res, GetCommentsByid(arrstr[i])...)
		arrstr = append(arrstr, GetCommentsByid(arrstr[i])...)	
		arrstr = arrstr[1:] // 删除开头1个元素
		i = -1
	}
	return res
}
func DeleteCommentByCid (c *gin.Context) {
	var delecomments []string
	delecomments = append(delecomments,GetAllSonComments(c.Param("id"))...)
	for _,v := range delecomments {
		MycommentModel.DB.Remove(bson.M{"_id": bson.ObjectIdHex(v)})
		MylikeModel.DB.Remove(bson.M{"id": v})
	}
	c.JSON(http.StatusOK, &ApiResponse {
		Code: 200,
		Type: "success",
		Message:  "",
	})
}

总结

这次作业担任了后端方面的工作,学会了用go的gin框架开启服务,配合mongodb可以为前端提供所需的API服务.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值