MongoDB基本概念与使用
MongoDB官方文档:MongoDB Documentation
1.
2. 基本操作
2.1 数据库
# 选择或创建数据库(如果没有数据库会直接创建)
use 数据库名
# 查看有权限查看的所有数据库
show dbs
# 删除数据库
db.dropDatabase()
admin : 从权限的角度来看,这是"root"数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器。
local: 这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合
config : 当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息
3. 集合
3.1 删除集合
db.<集合>.drop()
使用
drop
之后所有文档和相关的索引都会删除
3.2 插入
# 插入单个
db.<集合>.insertOne(<JSON对象>)
# 插入多个
db.<集合>.insertMany(<JSON对象>)
# 示例
db.fruit.insertOne({name: "apple"})
{
acknowledged: true,
insertedId: ObjectId('65ec8a0ad4e4510dcf3f07ca')
}
db.fruit.insertMany([{name: "orange"},{name: "banana"},{name: "pear"}])
{
acknowledged: true,
insertedIds: {
'0': ObjectId('65ec8a8fd4e4510dcf3f07cb'),
'1': ObjectId('65ec8a8fd4e4510dcf3f07cc'),
'2': ObjectId('65ec8a8fd4e4510dcf3f07cd')
}
}
3.3 查询
# 单条件查询
db.movies.find({"year":1975})
# 多条件and查询
db.movies.find({"year":1989,"title":"Batman"})
# and的另一种形式
db.movies.find({$and:[{"title":"Batman"},{"category":"action"H})
# 多条件or查询
db.movies.find({$or:[{"year":1989},""title":"Batman"]})
# 按正则表达式查找
db.movies.find({"title":/^B/})
和 Mysql 查询逻辑对照表
查询子文档
# form 中包含一个子文档
db.fruit.insertOne ({
name:"apple",
from: {
country:"China",
province:"Guangdon"
}
})
# 想要查询子文档
db.fruit.find( {"from.country": "China"} ) # 写文档的路径
db.fruit.find( {"from": { country: "China" } } ) # 不正确的写法
查询数组
# 文档color字段是数组
db.fruit.insertOne ([
{"name": "Apple", color: ["red", "green"] },
{"name": "Mango", color: ["yellow", "green"] }
])
# 查找color字段里面有红色的
db.fruit.find({ color: "red" })
# 查找color字段里面有红色或者黄色的
db.fruit.find({$or: [{color: "red" }, {color: "yellow"}]})
查询数组中的对象
db.movies.insertOne( {
"title":"Raiders of the Lost Ark",
"filming_locations": [
{"city": "Los Angeles", "state": "CA", "country": "USA" },
{"city": "Rome", "state": "Lazio", "country": "Italy"},
{"city": "Florence", "state": "SC", "country":"USA"},
]
})
// 查找城市是Rome的记录
db.movies.find({"filming_locations.city": "Rome"})
$eleMatch,表示必须是同一个子对象满足多个条件,考虑一下两个查询
# 匹配那些数组中任意元素满足 city 为 Rome 和 数组中另一个元素满足 country 为 USA 的文档
db.getCollection('movies').find({
"filming_locations.city":"Rome",
"filming_locations.country":"USA"
})
# 使用 $elemMatch 操作符时,它会确保在 filming_locations 数组内的单个元素内同时满足 city 为 "Rome" 和 country 为 "USA" 这两个条件。
db.getCollection('movies').find({
"filming_locations": {
SelemMatch:{"city":"Rome","country":"USA"}
})
控制返回的字段
# _id:0 表示不返回id字段
# from:1 表示返回from字段
# 并且只返回指定的字段
db.fruit.find({"name": "apple"},{"_id":0, from:1})
3.4 删除
remove
需要配合查询条件使用,并且如果指定空条件会删除所有文档
# 删除a等于1的文档
db.fruit.remove({a:1})
# 删除a小于1的文档
db.fruit.remove({a: { $lt: 5 })
# 删除所有记录(空的删除条件)
db.fruit.remove({})
# 报错,因为没有指定删除条件
db.furit.remove()
3.5 更新
# 查询name为apple的记录
# 将记录的from字段设置为China
db.fruit.updateOne({name: "apple"}, {$set: {from: "China"}})
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}
注意事项:
updateOne
无论匹配了多少条,只更新第一条
updateMany
匹配多少条,更新多少条
4. Mongodb go 客户端使用
import (
"context"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"log"
"time"
)
var client *mongo.Client
// Replace the placeholder with your Atlas connection string
const uri = "mongodb://mongo_E352Yy:mongo_3DhYJ6@xxx.xxx.xxx.xxx:27017/?maxPoolSize=20&w=majority"
func init() {
// 设置客户端连接选项
opts := options.Client().ApplyURI(uri)
opts.SetConnectTimeout(3 * time.Second)
// 连接到 MongoDB
var err error
client, err = mongo.Connect(context.Background(), opts)
if err != nil {
log.Fatalf("Failed to connect to MongoDB: %v", err)
}
// 检查连接是否成功
err = client.Ping(context.Background(), nil)
if err != nil {
log.Fatalf("Failed to ping MongoDB: %v", err)
}
log.Println("Connected to MongoDB")
}
依赖注入方式管理mongoDB连接
// Mongo 是一个抽象的MongoDB客户端接口
type Mongo interface {
GetClient() (*mongo.Client, error)
Close(context.Context) error
}
// MongoDBClient 实现了MongoDBClientInterface接口
type MongoDBClient struct {
client *mongo.Client
}
// NewMongoDBClient 是一个工厂函数,它负责初始化MongoDB客户端并返回其接口
func NewMongoDBClient(cfg *MongoDBConfig) (Mongo, error) {
ctx := context.Background()
clientOptions := options.Client().ApplyURI(cfg.Uri)
client, err := mongo.Connect(ctx, clientOptions)
if err != nil {
return nil, err
}
err = client.Ping(ctx, nil)
if err != nil {
defer client.Disconnect(ctx)
return nil, err
}
fmt.Println("Connected to MongoDB")
return &MongoDBClient{client: client}, nil
}
// "mongodb://mongo_E352Yy:mongo_3DhYJ6@xxx.xxx.xxx.xxx:27017/?maxPoolSize=20&w=majority"
type MongoDBConfig struct {
Uri string `yaml:"uri"`
Address string `yaml:"address"`
Username string `yaml:"username"`
Password string `yaml:"password"`
MaxPoolSize int `yaml:"maxPoolSize"`
}
func GetMongoDBConfig() (*MongoDBConfig, error) {
config := new(MongoDBConfig)
file, err := os.ReadFile("mongodb.yaml")
if err != nil {
return nil, err
}
//fmt.Println(string(file))
err = yaml.Unmarshal(file, config)
if err != nil {
return nil, err
}
config.Uri = fmt.Sprintf("mongodb://%s:%s@%s/?maxPoolSize=%d", config.Username, config.Password, config.Address, config.MaxPoolSize)
return config, nil
}
// GetClient 返回已连接的MongoDB客户端实例
func (mc *MongoDBClient) GetClient() (*mongo.Client, error) {
return mc.client, nil
}
// Close 断开与MongoDB的连接
func (mc *MongoDBClient) Close(ctx context.Context) error {
return mc.client.Disconnect(ctx)
}
编写 wire.go 文件
//go:build wireinject
// +build wireinject
package MongDB
import (
"github.com/google/wire"
)
func InitializeService() (*MyService, error) {
panic(wire.Build(
GetMongoDBConfig,
NewMongoDBClient,
NewMyService,
))
}
生成的 wire_gen.go 文件
// Code generated by Wire. DO NOT EDIT.
//go:generate go run -mod=mod github.com/google/wire/cmd/wire
//go:build !wireinject
// +build !wireinject
package MongDB
// Injectors from wire.go:
func InitializeService() (*MyService, error) {
mongoDBConfig, err := GetMongoDBConfig()
if err != nil {
return nil, err
}
mongo, err := NewMongoDBClient(mongoDBConfig)
if err != nil {
return nil, err
}
myService := NewMyService(mongo)
return myService, nil
}
5. 聚合查询
Mysql 常用步骤和 SQL 对比
评论区