基于Gin + WebSocket + MongoDB 的IM即时聊天Demo(四)

420 阅读2分钟

「这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战」。

github地址:github.com/CocaineCong…

B站教程地址:www.bilibili.com/video/BV1BP…

2.5 插入与查询

2.5.1 插入数据

我们使用的是mongoDB进行消息的存储,MongoDB的插入非常简单,文档数据库,插入json格式即可。

  • 定义一个存储的数据类型
type Trainer struct {
	Content 	string `bson:"content"`   // 内容
	StartTime 	int64  `bson:"startTime"` // 创建时间
	EndTime 	int64  `bson:"endTime"`   // 过期时间
	Read 		uint   `bson:"read"`      // 已读
}
  • 传入数据库,用户ID,内容,是否已读,过期时间
func InsertMsg(database string, id string, content string, read uint, expire int64) (err error) {
	collection := conf.MongoDBClient.Database(database).Collection(id)
	comment := ws.Trainer{
		Content:   content,
		StartTime: time.Now().Unix(),
		EndTime:   time.Now().Unix() + expire,
		Read:      read,
	}
	_, err = collection.InsertOne(context.TODO(),comment)
	return
}

2.5.2 查询数据

MongoDB的查询也非常容易,按照json格式进行查询。

  • 定义一个存储对象的切片
var resultsMe []ws.Trainer
  • 通过用户id查询所有的用户消息
idCollection := conf.MongoDBClient.Database(database).Collection(id)
  • 根据传入的time 定义一个过滤器,进行这个时间内的查询。
filter := bson.M{"startTime": bson.M{"$lt": time}}
  • 根据filter进行查询,然后再通过时间进行倒序排序,并且限定页数
sendIdTimeCursor, err := sendIdCollection.Find(context.TODO(), filter,
	options.Find().SetSort(bson.D{{"StartTime", -1}}), options.Find().
	SetLimit(int64(pageSize)))
  • 把数据查询数据传入到resultsMe中
err = idTimeCurcor.All(context.TODO(), &resultsMe) 

2.6 对方不在线

  • 广播信息
	case broadcast := <-Manager.Broadcast:
		message := broadcast.Message
		sendId := broadcast.Client.SendID
		flag := false // 默认对方不在线
  • 如果没有这个人的话就一直找就可以了
for id, conn := range Manager.Clients {
	if id != sendId {
		continue
	}
	select {
	case conn.Send <- message:
		flag = true
	default:
		close(conn.Send)
		delete(Manager.Clients, conn.ID)
	}
}
  • 还是找到的话

就可以当作已读信息,存储

if flag {
	log.Println("对方在线应答")
	replyMsg := &ReplyMsg{
		Code:    e.WebsocketOnlineReply,
		Content: "对方在线应答",
	}
	msg , err := json.Marshal(replyMsg)
	_ = broadcast.Client.Socket.WriteMessage(websocket.TextMessage, msg)
	err = InsertMsg(conf.MongoDBName, id, string(message), 1, int64(3*month))
	if err != nil {
		fmt.Println("InsertOneMsg Err", err)
	}
}
  • 如果没有找到的话,就是未读消息了。
else {
	log.Println("对方不在线")
	replyMsg := ReplyMsg{
		Code:    e.WebsocketOfflineReply,
		Content: "对方不在线应答",
	}
	msg , err := json.Marshal(replyMsg)
	_ = broadcast.Client.Socket.WriteMessage(websocket.TextMessage, msg)
	err = InsertMsg(conf.MongoDBName, id, string(message), 0, int64(3*month))
	if err != nil {
		fmt.Println("InsertOneMsg Err", err)
	}
}

3. 演示

  • 测试http连接

在这里插入图片描述

  • 进行ws连接,连接服务器

在这里插入图片描述

  • 当id=1上线,但是id=2没上线的时候发送消息 在这里插入图片描述
  • 当id=2上线之后

在这里插入图片描述

  • 再次发消息,就是在线应答了

在这里插入图片描述

  • 这边就实时接受到消息了 在这里插入图片描述
  • 获取历史信息

在这里插入图片描述

4. 源码地址

github地址

github.com/CocaineCong…