0%

MongoDB 使用

基本操作

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
// 选择数据库
use testdb;
// 打印所有文档
db.clusters.find().pretty();
// 删除文档
db.clusters.remove({"name": "test"});
db.workspaces.remove({"createTime": { $gte : new ISODate("2021-07-01T20:15:31Z") }})
// 更新文档
db.clusters.update({'name':'test100'},{$set:{'kubeConfig':'111'}})
db.workspaces.updateMany({"createTime": { $gte : new ISODate("2021-07-05T06:43:18.456Z") , $lte : new ISODate("2021-07-05T06:53:18.456Z") }},{$set:{'creator.acctID': new NumberLong("2100000924")}})
// 插入文档
db.records.insertOne({"RunID":"606d866135cece2969a106c9"})
// 创建索引
db.pipelines.createIndex({"triggerTime": -1, "createTime": -1})
// 查看索引
db.pipelines.getIndexes()
// 删除索引
db.col.dropIndexes()
db.pipelines.dropIndex("索引名称")
// 复制文档
var newOne = db.clusters.findOne({name: 'devbox'})
newOne._id = ObjectId('60702cf406aa28fd97c11011')
db.clusters.insertOne(newOne)
// 备份数据库
mongodump -d cp -o mongo-cp
// 恢复数据库
mongorestore -d cp cp
// 从 json 导入数据
mongoimport --db test --collection docs --file example2.json

K8S 中部署 MongoDB 副本集

参考:https://kubernetes.io/blog/2017/01/running-mongodb-on-kubernetes-with-statefulsets/

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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
apiVersion: v1
kind: Service
metadata:
name: mongo
labels:
app: mongo
spec:
ports:
- name: mongo
port: 27017
targetPort: 27017
clusterIP: None
selector:
app: mongo
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mongo
spec:
selector:
matchLabels:
app: mongo
serviceName: "mongo"
replicas: 3
template:
metadata:
labels:
app: mongo
spec:
serviceAccountName: mongo
containers:
- name: mongo
image: mongo:latest
command:
- mongod
- "--bind_ip_all"
- "--replSet"
- rs0
ports:
- containerPort: 27017
volumeMounts:
- name: mongo-data
mountPath: /data/db
- name: mongo-sidecar
image: cvallance/mongo-k8s-sidecar
env:
- name: MONGO_SIDECAR_POD_LABELS
value: "app=mongo"
- name: KUBE_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: KUBERNETES_MONGO_SERVICE_NAME
value: "mongo"
volumes:
- name: mongo-data
emptyDir: {}
---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
app: mongo
name: mongo
namespace: mongo
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: mongo
namespace: mongo
labels:
app: mongo
rules:
- apiGroups: [ "" ]
resources: [ "pods" ]
verbs: [ "list" ]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: mongo
namespace: mongo
labels:
app: mongo
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: mongo
subjects:
- kind: ServiceAccount
name: mongo

部署完成进行初始化(如果以上 yaml 中的 sidecar 工作正常就不需要手动初始化)

1
2
3
4
5
kd-cp exec -it -n mongo mongo-0 -- bash
// 进入 mongo 交互窗口
cfg = { _id:"rs0" , members: [{ _id: 0, host: "mongo-0.mongo.mongo"},{ _id: 1, host: "mongo-1.mongo.mongo"},{ _id: 2, host: "mongo-2.mongo.mongo"}] };
rs.initiate(cfg)
rs.status()

连接数据库使用如下 URL:

1
mongodb://mongo-0.mongo.mongo,mongo-1.mongo.mongo,mongo-2.mongo.mongo/?replicaSet=rs0

如此部署的 MongoDB 只能在 K8S 集群中使用。

watch 字段变化

参考:https://www.cnblogs.com/flipped/p/mongo-watch-specified-fields.html
可以 watch 的事件类型: https://docs.mongodb.com/manual/reference/change-events/

1
2
3
4
5
6
func watch(coll *mongo.Collection) {
match := bson.D{{"operationType", "update"},
{"updateDescription.updatedFields.name", bson.D{{"$exists", true}}}}
coll.Watch(context.Background(), mongo.Pipeline{{{"$match", match}}},
options.ChangeStream().SetFullDocument(options.UpdateLookup))
}

bson 反序列化到结构体

1
2
3
4
5
6
cluster = ⊧.Cluster{}
if fullDocument, ok := fullDocument.(bson.M); ok {
data, _ := bson.Marshal(fullDocument)
// 使用 bson.Unmarshal 应该也可以
_ = bson.UnmarshalWithRegistry(bson.DefaultRegistry, data, cluster)
}

性能调优

更新多层数组结构嵌套的数据

1
2
3
4
5
6
7
8
9
10
11
Post.findOneAndUpdate(
{ 'posts.replies._id': _id },
{ $set: { 'posts.$[post].replies.$[reply].text': "something1" } },
{ arrayFilters: [{ 'post._id': postId }, { 'reply._id': _id }]}
)

# 或者先查出目标的索引然后使用索引来更新
Post.findOneAndUpdate(
{ 'posts.replies._id': _id },
{ $set: { 'posts.0.replies.2.text': "something1" } },
)
本文到此结束  感谢您的阅读