golang Mongodb 按要求查询子集数据和直接修改子集数据

package main

import (
	"encoding/json"
	"fmt"
	"strconv"
)

const (
	DB_NAME    = "chat"
	TABLE_NAME = "person_log"
)

type PersonalChatLogMsg struct {
	Key      string
	ChatInfo []*PersonalChatLog
}

type PersonalChatLog struct {
	LogId    int64
	Talker   int64
	TargetId int64
	Content  string
	IsRead   bool
}

func GetChatLogKey(talkId, targetId int64) string {
	var key string
	if talkId > targetId {
		key = fmt.Sprintf("%d_%d", targetId, talkId)
	} else {
		key = fmt.Sprintf("%d_%d", talkId, targetId)
	}
	return key
}

func AddChatLog(info *PersonalChatLog) { //增加聊天记录
	mongo, err := mgo.Dial("mongodb://root:[email protected]:27017") // 建立连接
	defer mongo.Close()
	if err != nil {
		panic(err)
	}
	col := mongo.DB(DB_NAME).C(TABLE_NAME) //选择数据库和集合
	var obj *PersonalChatLogMsg
	key := GetChatLogKey(info.Talker, info.TargetId) //按id排序组合字符串key
	err1 := col.Find(bson.M{"key": key}).One(&obj)
	if err1 != nil && err1 != mgo.ErrNotFound {
		panic(err1)
	}
	if err1 == mgo.ErrNotFound {
		obj = &PersonalChatLogMsg{
			Key:      key,
			ChatInfo: []*PersonalChatLog{info},
		}
		col.Insert(&obj)
	} else {
		err2 := col.Update(bson.M{"key": key}, bson.M{"$push": bson.M{"chatinfo": info}})
		if err2 != nil && err2 != mgo.ErrNotFound {
			panic(err2)
		}
	}
}

func ReadChatLog(logId int64) { //修改子集列表ChatInfo下的某一条数据的其中IsRead字段
	mongo, err := mgo.Dial("mongodb://root:[email protected]:27017") // 建立连接
	defer mongo.Close()
	if err != nil {
		panic(err)
	}
	col := mongo.DB(DB_NAME).C(TABLE_NAME)                                                                 //选择数据库和集合
	err1 := col.Update(bson.M{"chatinfo.logid": logId}, bson.M{"$set": bson.M{"chatinfo.$.isread": true}}) //未读消息
	if err1 != nil {
		panic(err1)
	}
}

func GetUnReadChatLog(pid int64) []*PersonalChatLog { //查找该id的所有未读私聊信息
	mongo, err := mgo.Dial("mongodb://root:[email protected]:27017") // 建立连接
	defer mongo.Close()
	if err != nil {
		panic(err)
	}
	col := mongo.DB(DB_NAME).C(TABLE_NAME)
	var chatlst []*PersonalChatLog
	value := strconv.Itoa(int(pid))
	queryBson := bson.M{"key": bson.M{"$regex": value}, "chatinfo.targetid": pid, "chatinfo.isread": false}
	m := []bson.M{ //这里的顺序不能乱  必须这样
		bson.M{"$unwind": "$chatinfo"},
		bson.M{"$match": queryBson},
		bson.M{"$project": bson.M{"chatinfo": 1, "_id": 0}},
	}
	query := col.Pipe(m)
	var list []interface{}
	err1 := query.All(&list)
	if err1 != nil {
		panic(err1)
	}
	for _, n := range list { //因为找出来的数据都是bson.M格式的,要通过json转PersonalChatLog格式
		var chat *PersonalChatLog
		info := n.(bson.M)
		m1 := info["chatinfo"]
		j, _ := json.Marshal(m1)
		json.Unmarshal(j, &chat)
		chatlst = append(chatlst, chat)
	}
	return chatlst
}

func main() {
	//数据结构为一个表多个PersonalChatLogMsg数据格式,key为两个玩家id从小到大组成的字符串 ChatInfo为聊天记录的列表
	// type PersonalChatLogMsg struct {
	//	Key      string
	//	ChatInfo []*PersonalChatLog
	//}

	talkId := int64(188888888)
	targetId := int64(199999999)
	info := &PersonalChatLog{
		LogId:    1,
		Talker:   talkId,
		TargetId: targetId,
		Content:  "hello world",
		IsRead:   false,
	}
	AddChatLog(info)                       //增加聊天记录
	ReadChatLog(1)                         //阅读聊天记录
	chatList := GetUnReadChatLog(targetId) //查找该id的所有未读私聊信息
	if len(chatList) != 0 {
		for _, chat := range chatList {
			fmt.Println("chatList", chat.LogId)
		}
	}

	info.LogId = 2
	AddChatLog(info)                        //增加聊天记录
	chatList1 := GetUnReadChatLog(targetId) //查找该id的所有未读私聊信息
	if len(chatList1) != 0 {
		for _, chat := range chatList1 {
			fmt.Println("chatList1", chat.LogId)
		}
	}

	// 后续添加聊天记录的时候报了一个bug, Resulting document after update is larger than 16777216;
	// 查了相关文档才知道原来mongodb数据库单个数据大小不能超过16MB,这里因为ChatInfo列表数据太大超过了16MB.
	// 所以这种格式的存储是有问题的,没想到更好的方法,只能修改一个表一个ChatInfo列表格式,这样每个聊天记录的大小不会超过16MB.
	// 只不过这样每两个玩家聊天就会有一个聊天表,导致表太多。
}

你可能感兴趣的:(技术)