二丫讲梵 二丫讲梵
首页
  • 最佳实践
  • 迎刃而解
  • Nginx
  • Php
  • Zabbix
  • AWS
  • Prometheus
  • Grafana
  • CentOS
  • Systemd
  • Docker
  • Rancher
  • Ansible
  • Ldap
  • Gitlab
  • GitHub
  • Etcd
  • Consul
  • RabbitMQ
  • Kafka
  • MySql
  • MongoDB
  • OpenVPN
  • KVM
  • VMware
  • Other
  • ELK
  • K8S
  • LLM
  • Nexus
  • Jenkins
  • 随写编年
  • 家人物语
  • 追忆青春
  • 父亲的朋友圈
  • 电影音乐
  • 效率工具
  • 博客相关
  • Shell
  • 前端实践
  • Vue学习笔记
  • Golang学习笔记
  • Golang编程技巧
  • 学习周刊
  • Obsidian插件周刊
关于
友链
  • 本站索引

    • 分类
    • 标签
    • 归档
  • 本站页面

    • 导航
    • 打赏
  • 我的工具

    • 备忘录清单 (opens new window)
    • json2go (opens new window)
    • gopher (opens new window)
    • 微信MD编辑 (opens new window)
    • 国内镜像 (opens new window)
    • 出口IP查询 (opens new window)
    • 代码高亮工具 (opens new window)
  • 外站页面

    • 开往 (opens new window)
    • ldapdoc (opens new window)
    • HowToStartOpenSource (opens new window)
    • vdoing-template (opens new window)
GitHub (opens new window)

二丫讲梵

行者常至,为者常成
首页
  • 最佳实践
  • 迎刃而解
  • Nginx
  • Php
  • Zabbix
  • AWS
  • Prometheus
  • Grafana
  • CentOS
  • Systemd
  • Docker
  • Rancher
  • Ansible
  • Ldap
  • Gitlab
  • GitHub
  • Etcd
  • Consul
  • RabbitMQ
  • Kafka
  • MySql
  • MongoDB
  • OpenVPN
  • KVM
  • VMware
  • Other
  • ELK
  • K8S
  • LLM
  • Nexus
  • Jenkins
  • 随写编年
  • 家人物语
  • 追忆青春
  • 父亲的朋友圈
  • 电影音乐
  • 效率工具
  • 博客相关
  • Shell
  • 前端实践
  • Vue学习笔记
  • Golang学习笔记
  • Golang编程技巧
  • 学习周刊
  • Obsidian插件周刊
关于
友链
  • 本站索引

    • 分类
    • 标签
    • 归档
  • 本站页面

    • 导航
    • 打赏
  • 我的工具

    • 备忘录清单 (opens new window)
    • json2go (opens new window)
    • gopher (opens new window)
    • 微信MD编辑 (opens new window)
    • 国内镜像 (opens new window)
    • 出口IP查询 (opens new window)
    • 代码高亮工具 (opens new window)
  • 外站页面

    • 开往 (opens new window)
    • ldapdoc (opens new window)
    • HowToStartOpenSource (opens new window)
    • vdoing-template (opens new window)
GitHub (opens new window)
  • Shell编程

  • Go编程笔记

    • 开发技巧

      • go日常开发代码片段
      • golang交叉编译
      • 两个切片内容相减的几种方法
      • golang以结构体中某个字段进行排序
      • vscode开发golang报黄提示composite literal uses unkeyed fields
      • golang使用$in或$nin查询MongoDB是否在数组内的数据
      • golang使用$push和$addToSet往数组添加字段的异同
      • MongoDB自增ID在golang中的实践
        • 原生 MongoDB 语句
        • golang 的实现
      • golang数据类型转换汇总
      • 记录VSCode中写Go代码切换Sqlite无CGO依赖版本的过程以及遇到的五个问题
      • 企业微信自建应用-golang校验回调
      • 对接腾讯云未集成到SDK的接口开发实践小记
      • Go开发实践之Gin框架将前端的dist目录embed到二进制
    • 库包研究

    • 个人项目

  • 前端编程笔记

  • Go学习笔记

  • Vue-21年学习笔记

  • Vue-22年重学笔记

  • 编程世界
  • Go编程笔记
  • 开发技巧
二丫讲梵
2022-03-18
目录

MongoDB自增ID在golang中的实践

文章发布较早,内容可能过时,阅读注意甄别。

MongoDB 默认的 ID 不像 MySQL 那样的自增 ID,如果想要实现自增 ID,则需要借助于另一张表存放该表的 ID,每次存数据的时候,需要通过 findAndModify 方法对这个 ID 进行获取并加 1。

# 原生 MongoDB 语句

$ db.ids.save({name:"user", next_id:NumberInt("0")});
1

创建一个集合,专门存储其他表的自增信息,默认数字类型是int64,这里通过NumberInt()方法将其指定为int32。

查询该条记录:

$ db.getCollection('ids').find({})
{
    "_id" : ObjectId("6234313fb503f6bf2433f4e4"),
    "name" : "user",
    "next_id" : 0
}
1
2
3
4
5
6

新增用户的时候,直接调用获取 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"
});
1
2
3
4
5
6
7
8
9

注:因为 findAndModify 是一个方法完成更新查找两个操作,所以具有原子性,多线程不会冲突。

然后查询该条记录:

$ db.getCollection('user').find({})
{
    "_id" : 1,
    "username" : "eryajf",
    "site" : "https://wiki.eryajf.net"
}
1
2
3
4
5
6

# 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
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

自增 ID 从视觉上更加直观,与 DB 交互查询的时候也更加简便,某些场景中是可取的方案。

  • 参考:Mongodb 自动增长 自增 id 实现 (opens new window)
微信 支付宝
#MongoDB
上次更新: 2024/07/04, 22:40:37
golang使用$push和$addToSet往数组添加字段的异同
golang数据类型转换汇总

← golang使用$push和$addToSet往数组添加字段的异同 golang数据类型转换汇总→

最近更新
01
学习周刊-总第213期-2025年第22周
05-29
02
学习周刊-总第212期-2025年第21周
05-22
03
从赵心童世锦赛夺冠聊聊我的斯诺克情缘
05-16
更多文章>
Theme by Vdoing | Copyright © 2017-2025 | 点击查看十年之约 | 浙ICP备18057030号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式