@@ -1,58 +0,0 @@ 08.MongoDB自增ID在golang中的实践 | 凤凰涅槃进阶之路

08.MongoDB自增ID在golang中的实践

Abel sun2023年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