08.MongoDB自增ID在golang中的实践
2023年1月6日约 563 字大约 2 分钟
08.MongoDB自增ID在golang中的实践
MongoDB默认的ID不像MySQL那样的自增ID,如果想要实现自增ID,则需要借助于另一张表存放该表的ID,每次存数据的时候,需要通过findAndModify方法对这个ID进行获取并加1。
原生MongoDB语句
db.ids.save({name:"user", next_id:NumberInt("0")});
创建一个集合,专门存储其他表的自增信息,默认数字类型是int64
,这里通过NumberInt()
方法将其指定为int32
。
查询该条记录:
$ db.getCollection('ids').find({})
{
"_id" : ObjectId("6234313fb503f6bf2433f4e4"),
"name" : "user",
"next_id" : 0
}
新增用户的时候,直接调用获取ID:
$ db.user.save({
_id: NumberInt(db.ids.findAndModify({
update:{$inc:{'next_id':NumberInt("1")}},
query:{"name":"user"},
new:true
}).next_id),
username: "eryajf",
site:"https://wiki.eryajf.net"
});
注:
因为findAndModify是一个方法完成更新查找两个操作,所以具有原子性,多线程不会冲突。
然后查询该条记录:
$ db.getCollection('user').find({})
{
"_id" : 1,
"username" : "eryajf",
"site" : "https://wiki.eryajf.net"
}
golang的实现
golang的实现与语句差不多,这里只是做示例展示,其中的GetDataID("user")
在实际生产使用过程中,需要确保对其错误进行处理。
package main
import (
"context"
"fmt"
"learnmongo/public"
"log"
"math/rand"
"strconv"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
var DB *mongo.Database
func init() {
uri := "mongodb://root:123456@10.1.1.3:27017"
if uri == "" {
log.Fatal("You must set your 'MONGODB_URI' environmental variable. See\n\t https://docs.mongodb.com/drivers/go/current/usage-examples/#environment-variable")
}
client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri))
if err != nil {
panic(err)
}
DB = client.Database("class")
}
type UserMongo struct {
ID int32 `bson:"_id"`
Name string `bson:"name"`
Phone string `bson:"phone"`
Email string `bson:"email"`
}
func main() {
defer func() {
if err := public.InitDb().Disconnect(context.TODO()); err != nil {
panic(err)
}
}()
fmt.Println("start")
table := DB.Collection("user") // 指定表名为user
_, err := table.InsertMany(context.TODO(), []interface{}{
UserMongo{
ID: GetDataID("user"),
Name: "eryajf" + strconv.Itoa(rand.Intn(11)),
Phone: strconv.Itoa(rand.Intn(11)),
Email: strconv.Itoa(rand.Intn(5)) + "@qq.com",
},
UserMongo{
ID: GetDataID("user"),
Name: "liql" + strconv.Itoa(rand.Intn(11)),
Phone: strconv.Itoa(rand.Intn(11)),
Email: strconv.Itoa(rand.Intn(5)) + "@qq.com",
},
})
if err != nil {
fmt.Print(err)
return
}
fmt.Println("end「👋」")
}
func GetDataID(collname string) int32 {
table := DB.Collection("ids") // 指定表名为ids表
var result struct {
Name string `json:"name" bson:"name"`
NextID int32 `json:"next_id" bson:"next_id"`
}
table.FindOneAndUpdate(
context.TODO(),
bson.M{"name": collname},
bson.M{"$inc": bson.M{"next_id": 1}}).Decode(&result)
return result.NextID
}
自增ID从视觉上更加直观,与DB交互查询的时候也更加简便,某些场景中是可取的方案。
Powered by Waline v2.9.1