mongo命令
近期抽了一点时间,从头到尾梳理了这本书,其中书中的一些例子结合日常使用的基础,尽量的复现出来了。因为我使用的是mongo4.4.5的版本。所以部分例如group和mapreduce不再使用。而且官方有更好的方案实现同样的功能就没复现了。
以下是mongo相关功能的复现的命令。这里我推荐大家使用datagrip。
//
// 在mongo 4.4.5下测试
//
// -- $inc
db.games.insertOne({"game": "pinball", "user": "joe"})
db.games.updateOne({"game": "pinball", "user": "joe"}, {"$inc": {"score": 50}})
db.games.updateOne({"game": "pinball", "user": "joe"}, {"$inc": {"score": 150}})
db.games.findOne()
// -- 数组修改器
db.blog.insertOne({'title': 'A blog post', 'content': "..."})
db.blog.findOne()
db.blog.updateOne({'title': 'A blog post', 'content': "..."}, {
"$push": {'comments': {'name': 'joe', 'email': 'joe@example.com', 'content': 'nice post.'}}
})
db.blog.updateOne({'title': 'A blog post', 'content': "..."}, {
"$push": {'comments': {'name': 'bob', 'email': 'bob@example.com', 'content': 'good post.'}}
})
db.users.insertOne({'username': 'joe', 'emails': ['joe@example.com', 'joe@gmail.com']})
db.users.findOne({"username": "joe"})
db.users.find()
db.users.updateOne({"_id": ObjectId("60869b766aa39e193eab3f5b")}, {
"$addToSet": {'emails': 'joe@yahoo.com'}
})
db.users.updateOne({"_id": ObjectId("60869b766aa39e193eab3f5b")}, {
"$addToSet": {
'emails': {
'$each': ['joe@php.net', 'joe@python.org']
}
}
})
// 从数组末尾删除一个元素
db.users.updateOne({"_id": ObjectId("60869b766aa39e193eab3f5b")}, {
"$pop": {'emails': 1}
}
)
// 从数组头部删除
db.users.updateOne({"_id": ObjectId("60869b766aa39e193eab3f5b")}, {
"$pop": {'emails': -1}
}
)
// 特定条件删除
db.lists.insertOne({'todo': ['dishes', 'laundry', 'dry cleaning']})
db.lists.findOne()
db.lists.updateOne({'_id': ObjectId('60869f1e6aa39e193eab3f5d')},
{
'$pull': {'todo': 'laundry'}
}
)
// -- 数组的定位修改器
db.blog.find()
db.blog.updateOne({'title': 'A blog post', 'content': "..."},
{"$unset": {"posts": ''
}
}
)
db.posts.insertOne({"posts": {'article': 'hello world', 'post_id': 1}})
db.blog.updateOne({'title': 'A blog post', 'content': "..."},
{
"$push": {'posts': db.posts.findOne()}
}
)
db.posts.findOne()
db.blog.updateMany({"posts.posts.post_id": 1},
{
"$set": {'posts.$.posts.article': '你好世界!'}
}
)
// -- upsert
db.analytics.updateMany({"url": "/blog"},
{"$inc": {"visits": 1}}, true
)
db.analytics.findOne()
db.math.updateOne({"count": 25}, {"$inc": {"count": 3}}, {'upsert': true})
db.math.find()
// 多文档更新到底更新了多少文档
db.runCommand({getLastError: 1})
// findAndModify 查找后更新
db.processes.insertOne({'status': 'READY', 'priority': 0})
db.processes.findOne()
db.runCommand({
"findAndModify": "processes",
"query":
{
"status": "READY"
},
"sort":
{
"priority": -1
},
"update":
{
"$set":
{
"status": "RUNNING"
}
}
})
// 不等于
db.users.find()
db.users.findOne({"username":
{"$ne": "joe"}
})
// or查询
// in
db.users.find({"username":
{
"$in": ['joe']
}
})
// not in
db.users.find({"username":
{
"$nin": ['123']
}
})
// 多键or
db.users.find({"$or": [{'username': {'$in': ['123']}}, {'emails': {"$in": ['joe@php.net']}}]})
// mod, not运算
db.users.updateOne({"_id": ObjectId("60869b766aa39e193eab3f5b")}, {"$set": {"id_num": 6}}, {"upsert": true})
db.users.findOne()
// $mod 会将查询的值除以第一个给定值,若余数等于第二个给定值则返回该结果
db.users.findOne({"id_num": {"$mod": [5, 2]}})
db.users.findOne({"id_num": {"$not": {"$mod": [5, 2]}}})
// null 查找
db.c.insertMany([
{'y': 1},
{'y': 2},
{'y': null}
])
db.c.find({'y': null})
db.c.find({'z': null})
db.c.find({'z': {'$in': [null], "$exists": true}})
// 正则表达式
db.users.find({'username': /joe/i})
db.users.find({'username': /joey?/i})
// 正则表达式亦可插入数据库中
db.foo.insertOne({'bar': /baz/})
db.foo.find({'bar': /baz/})
// 查询数组
db.food.insertOne({'fruit': ['apple', 'banana', 'peach']})
db.food.find({'fruit': 'banana'})
db.food.insertOne({'fruit': ['apple', 'banana', 'kumquat']})
db.food.insertOne({'fruit': ['cherry', 'banana', 'apple']})
db.food.find({'fruit': {"$all": ['apple', 'banana']}})
db.food.find({'fruit': ['apple', 'banana', 'peach']})
db.food.find({'fruit': ['apple', 'banana']})
// 带元素位置
db.food.find({'fruit.0': 'apple'})
db.food.find({'fruit.2': "peach"})
// 查询数组的大小
db.food.find({'fruit': {'$size': 3}})
db.food.updateMany({}, {'$push': {'fruit': 'strawberry'}})
db.food.updateMany({}, {'$pull': {'fruit': 'strawberry'}})
db.food.updateMany({}, {"$push": {'fruit': 'strawberry'}, "$inc": {'size': 1}})
db.food.find()
// $slice 操作
// 前一个元素
db.food.findOne({}, {'fruit': {'$slice': 1}})
// 后一个元素
db.food.findOne({}, {'fruit': {'$slice': -1}})
// 起始,偏移多少个元素
// 跳过第一个元素,返回接下来的2个元素
db.food.findOne({}, {'fruit': {'$slice': [1, 2]}})
// -- 查询内嵌文档
db.blog.find()
// $ slemMatch 模糊命名条件句
// 用来部分指定匹配数组中的单个内嵌文档的限定条件
db.blog.find({"comments": {'$elemMatch': {"name": "joe"}}})
// -- $where查询
db.foo.insertOne({'apple': 1, 'banana': 6, 'peach': 3})
db.foo.insertOne({'apple': 8, 'spinach': 4, 'watermelon': 4})/
db.foo.find({"$where": "this.spinach + this.watermelon == 8"})
db.foo.find({"$where": "function() {return this.spinach + this.watermelon == 8}"})
// -- limit, skip和sort
db.c.find().limit(3)
// 跳过前一个,返回剩下的
db.c.find().skip(1)
// 1表示升序, -1表示降序
db.foo.find().sort({'apple': 1, 'peach': -1})
// -- 索引
db.users.find()
db.users.insertOne({'username': 'mark', 'id_num': 7, 'emails': []})
db.users.ensureIndex({'username': 1})
db.users.ensureIndex({'username': 1, 'id_num': -1})
db.users.insertOne({'username': 'bob', 'id_num': 17})
// -- 索引名称
db.users.ensureIndex({'id_num': -1}, {'name': 'index_idnum'})
// -- 唯一索引
db.games.find()
db.games.ensureIndex({'user': 1, 'game': 1}, {'unique': true})
// -- 消除重复
db.users.find()
db.users.insertOne({'username': 'bob', 'id_num': 11})
// It looks like you are running a MongoDB with version >3.0 and hence cannot remove dups by ensuring an index
db.users.ensureIndex({'username': 1}, {'unique': true, 'dropDups': true})
// -- 使用explain 和 hint
db.foo.find().explain()
db.c.insertMany([{'age': 20}, {'age': 30}, {'age': 10}])
db.c.find({'age': {"$gt": 20, '$lt': 30}}).explain()
// hint 强制使用某一个索引
db.users.find().hint({'username': 1})
// -- 索引管理
db.system.indexes.find()
// 修改索引
// 后台处理
db.users.ensureIndex({"username": 1}, {"background": true})
// 删除索引
db.runCommand({'dropIndexes': 'users', 'index': 'username_1'})
// 删除所有索引
db.runCommand({'dropIndexes': 'users', 'index': '*'})
// remove方式删除所有文档并不影响原有索引,但是删除整个collection会
// -- 地理空间索引
# loc表示坐标
db.shop.insertOne({loc : [10, 10]});
db.shop.insertOne({loc : [11, 10]});
db.shop.insertOne({loc : [10, 11]});
db.shop.insertOne({loc : [12, 15]});
db.shop.insertOne({loc : [16, 17]});
db.shop.insertOne({loc : [90, 90]});
db.shop.insertOne({loc : [150, 160]});
db.shop.find()
// 创建2d索引
db.shop.createIndex({loc: "2d"})
// 查找
db.shop.find({loc: {'$near': [11, 11]}})
db.shop.find({loc: {'$near': [11, 11], '$maxDistance': 5}})
// 查找矩形
db.shop.find({loc: {'$geoWithin': {'$box': [[9, 9], [11, 11]]}}})
// 查找圆形
db.shop.find({loc: {"$geoWithin": {'$center': [[10, 10], 2]}}})
// -- 聚合
// count
db.shop.count()
db.users.count({'username': 'bob'})
// distinct
db.runCommand({'distinct': 'users', 'key': 'username'})
// group
db.stocks.insertOne({'day': '2010/10/03', 'time': '10/3/2010 03:57:01 GMT-400', 'price': 4.23})
db.stocks.insertOne({'day': '2010/10/04', 'time': '10/4/2010 11:28:39 GMT-400', 'price': 4.27})
db.stocks.insertOne({'day': '2010/10/03', 'time': '10/3/2010 05:00:23 GMT-400', 'price': 4.10})
db.stocks.insertOne({'day': '2010/10/06', 'time': '10/6/2010 05:27:58 GMT-400', 'price': 4.30})
db.stocks.insertOne({'day': '2010/10/04', 'time': '10/4/2010 08:34:50 GMT-400', 'price': 4.01})
// 以下无法在mongo4中使用
db.runCommand({"group": {
'ns': 'stocks',
'key': 'day',
'initial': {
'time': 0
},
'$reduce': function(doc, prev) {
if (doc.time > prev.time) {
prev.time = doc.price;
prev.time = doc.time;
}
}
}})
// -- mapreduce
// Aggregation Pipeline as Alternative
//An aggregation pipeline provides better performance and usability than a map-reduce operation.
//
//Map-reduce operations can be rewritten using aggregation pipeline operators, such as $group, $merge, and others.
//
//For map-reduce operations that require custom functionality, MongoDB provides the $accumulator and $function aggregation operators starting in version 4.4. Use these operators to define custom aggregation expressions in JavaScript.
//
//For examples of aggregation pipeline alternatives to map-reduce operations, see Map-Reduce to Aggregation Pipeline and Map-Reduce Examples.
db.orders.insertMany([
{ _id: 1, cust_id: "Ant O. Knee", ord_date: new Date("2020-03-01"), price: 25, items: [ { sku: "oranges", qty: 5, price: 2.5 }, { sku: "apples", qty: 5, price: 2.5 } ], status: "A" },
{ _id: 2, cust_id: "Ant O. Knee", ord_date: new Date("2020-03-08"), price: 70, items: [ { sku: "oranges", qty: 8, price: 2.5 }, { sku: "chocolates", qty: 5, price: 10 } ], status: "A" },
{ _id: 3, cust_id: "Busby Bee", ord_date: new Date("2020-03-08"), price: 50, items: [ { sku: "oranges", qty: 10, price: 2.5 }, { sku: "pears", qty: 10, price: 2.5 } ], status: "A" },
{ _id: 4, cust_id: "Busby Bee", ord_date: new Date("2020-03-18"), price: 25, items: [ { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" },
{ _id: 5, cust_id: "Busby Bee", ord_date: new Date("2020-03-19"), price: 50, items: [ { sku: "chocolates", qty: 5, price: 10 } ], status: "A"},
{ _id: 6, cust_id: "Cam Elot", ord_date: new Date("2020-03-19"), price: 35, items: [ { sku: "carrots", qty: 10, price: 1.0 }, { sku: "apples", qty: 10, price: 2.5 } ], status: "A" },
{ _id: 7, cust_id: "Cam Elot", ord_date: new Date("2020-03-20"), price: 25, items: [ { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" },
{ _id: 8, cust_id: "Don Quis", ord_date: new Date("2020-03-20"), price: 75, items: [ { sku: "chocolates", qty: 5, price: 10 }, { sku: "apples", qty: 10, price: 2.5 } ], status: "A" },
{ _id: 9, cust_id: "Don Quis", ord_date: new Date("2020-03-20"), price: 55, items: [ { sku: "carrots", qty: 5, price: 1.0 }, { sku: "apples", qty: 10, price: 2.5 }, { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" },
{ _id: 10, cust_id: "Don Quis", ord_date: new Date("2020-03-23"), price: 25, items: [ { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" }
])
// 不再支持
db.orders.mapReduce(
function() {
emit(this.cust_id, this.price);
},
function(keyCustId, valuesPrices) {
return Array.sum(valuesPrices);
},
{ out: "map_reduce_example" }
)
// --固定集合
db.createCollection('my_collection', {capped: true, size: 100000});
// 指定文档上限
db.createCollection('my_collection1', {capped: true, size: 100000, max: 100});
// 转换普通集合为固定集合
db.runCommand({convertToCapped: 'test', size: 10000})
// 自然排序
db.test.find().sort({'$natural': -1})
// -- DBRef
original_id = ObjectId()
db.places.insertOne({
"_id": original_id,
"name": "Broadway Center",
"url": "bc.example.net"
})
db.people.insertOne({
"name": "Erin",
"places_id": original_id,
"url": "bc.example.net/Erin"
})
db.people.find({'name': 'Erin'});
db.A.insertMany([
{'value': '1'},
{'value': '2'},
{'value': '3'}
])
db.A.find()
db.B.insertMany([
{'Apid': [new DBRef('A', ObjectId('6094e7ee1fb25054635c1980'))], 'value': 3},
{'Apid': [new DBRef('A', ObjectId('6094e7ee1fb25054635c1981'))], 'value': 7}
])
db.B.find()
db.address_home.insertOne({
'address': 'houston'
})
db.address_home.find()
db.users.insertOne({
'username': 'jane',
'id_num': 13,
'address': {
'$ref': 'address_home',
'$id': ObjectId('6094ef571fb25054635c1987'),
'$db': 'cluster_map'
}
})
var user = db.users.findOne({"name":"jane"})
var dbRef = user.address
db[dbRef.$ref].findOne({"_id":ObjectId(dbRef.$id)})
// 副本集群测试
// https://www.huaweicloud.com/articles/716120f070b9defaba79ab083e59ff3a.html
一些准备工作
我这里使用的mongo的容器。
有关mongo的副本集群,实现的docker-compose.yml如下
version: '3.3'
services:
mongo-master:
hostname: mongo
image: mongo:4.4.5
container_name: mongo
networks:
- mongo-network
ports:
- '27038:27017'
environment:
- MONGO_INITDB_ROOT_USERNAME=root
- MONGO_INITDB_ROOT_PASSWORD=abc
- TZ=Asia/Shanghai
volumes:
- ./data:/data/db
- ./keyFiles/mongo-key:/keyFiles/mongo-key
- ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
- ./mongod.conf:/etc/mongod.conf
- /etc/localtime:/etc/localtime:ro
command: ["mongod", "--replSet", "BigBoss", "--keyFile", "/keyFiles/mongo-key"]
restart: always
mongo-sec1:
hostname: mongo-sec1
image: mongo:4.4.5
container_name: mongo-secondary01
networks:
- mongo-network
ports:
- '27037:27017'
environment:
- MONGO_INITDB_ROOT_USERNAME=root
- MONGO_INITDB_ROOT_PASSWORD=abc
- TZ=Asia/Shanghai
volumes:
- ./secondary01_data:/data/db
- ./keyFiles/mongo-key:/keyFiles/mongo-key
- ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
- ./mongod.conf:/etc/mongod.conf
- /etc/localtime:/etc/localtime:ro
command: ["mongod", "--replSet", "BigBoss", "--keyFile", "/keyFiles/mongo-key"]
restart: always
mongo-sec2:
hostname: mongo-sec2
image: mongo:4.4.5
container_name: mongo-secondary02
networks:
- mongo-network
ports:
- '27039:27017'
environment:
- MONGO_INITDB_ROOT_USERNAME=root
- MONGO_INITDB_ROOT_PASSWORD=abc
- TZ=Asia/Shanghai
volumes:
- ./secondary02_data:/data/db
- ./keyFiles/mongo-key:/keyFiles/mongo-key
- ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
- ./mongod.conf:/etc/mongod.conf
- /etc/localtime:/etc/localtime:ro
command: ["mongod", "--replSet", "BigBoss", "--keyFile", "/keyFiles/mongo-key"]
restart: always
mongo-arb:
hostname: mongo-arb
image: mongo:4.4.5
container_name: mongo-arbiter
networks:
- mongo-network
ports:
- '27040:27017'
environment:
- MONGO_INITDB_ROOT_USERNAME=root
- MONGO_INITDB_ROOT_PASSWORD=abc
- TZ=Asia/Shanghai
volumes:
- ./arbiter_data:/data/db
- ./keyFiles/mongo-key:/keyFiles/mongo-key
- ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
- ./mongod.conf:/etc/mongod.conf
- /etc/localtime:/etc/localtime:ro
command: ["mongod", "--replSet", "BigBoss", "--keyFile", "/keyFiles/mongo-key"]
restart: always
networks:
mongo-network:
driver: bridge
ipam:
driver: default
mongo-init.js文件如下:
db.auth('root', 'abc')
db = db.getSiblingDB('test_map')
db.createUser({
user: 'test_admin',
pwd: 'abc',
roles: [
{
role: 'dbOwner',
db: 'test_map',
},
],
});
mongod.conf文件如下:
systemLog:
destination: file
path: "/var/log/mongodb/mongod.log"
logAppend: true
processManagement:
fork: true
net:
#bindIp: 127.0.0.1
port: 27017
setParameter:
enableLocalhostAuthBypass: false
security:
authorization: enabled # enabled/disabled #开启客户端认证
javascriptEnabled: true #启用或禁用服务器端JavaScript执行
keyFile: /keyFiles/mongo-key # 密钥路径
# clusterAuthMode: <string> #集群认证方式
# enableEncryption: <boolean>
# encryptionCipherMode: <string>
# encryptionKeyFile: <string>
# kmip:
# keyIdentifier: <string>
# rotateMasterKey: <boolean>
# serverName: <string>
# port: <string>
# clientCertificateFile: <string>
# clientCertificatePassword: <string>
# serverCAFile: <string>
# sasl:
# hostName: <string>
# serviceName: <string>
# saslauthdSocketPath: <string>
operationProfiling: #性能分析
slowOpThresholdMs: 100 #认定为查询速度缓慢的时间阈值,超过该时间的查询即为缓慢查询,会被记录到日志中, 默认100
mode: off #operationProfiling模式 off/slowOp/all 默认off
replication: # 复制集相关
# oplogSizeMB: <int>
replSetName: 'replicaset01'
# secondaryIndexPrefetch: <string>
# enableMajorityReadConcern: <boolean>
# sharding: #集群分片相关
# clusterRole: <string>
# archiveMovedChunks: <boolean>
# auditLog:
# destination: <string>
# format: <string>
# path: <string>
# filter: <string>
# snmp:
# subagent: <boolean> #当设置为true,SNMP作为代理运行
# master: <boolean> #当设置为true,SNMP作为主服务器运行
# basisTech:
# rootDirectory: <string>
storage:
dbPath: /data/db #数据库,默认/data/db,如果使用软件包管理安装的查看/etc/mongod.conf
indexBuildRetry: true #重启时,重建不完整的索引
# repairPath: <string> #--repair操作时的临时工作目录,默认为dbPath下的一个_tmp_repairDatabase_<num>的目录
journal:
enabled: true #启动journal,64位系统默认开启,32位默认关闭
# commitIntervalMs: <num> #journal操作的最大时间间隔,默认100或30
directoryPerDB: false #使用单独的目录来存储每个数据库的数据,默认false,如果需要更改,要备份数据,删除掉dbPath下的文件,重建后导入数据
# syncPeriodSecs: 60 #使用fsync来将数据写入磁盘的延迟时间量,建议使用默认值
engine: wiredTiger #存储引擎,mmapv1/wiredTiger/inMemory 默认wiredTiger
# mmapv1:
# preallocDataFiles: <boolean>
# nsSize: <int>
# quota:
# enforced: <boolean>
# maxFilesPerDB: <int>
# smallFiles: <boolean>
# journal:
# debugFlags: <int>
# commitIntervalMs: <num>
# wiredTiger:
# engineConfig:
# cacheSizeGB: <number> #缓存大小
# journalCompressor: <string> #数据压缩格式 none/snappy/zlib
# directoryForIndexes: <boolean> #将索引和集合存储在单独的子目录下,默认false
# collectionConfig:
# blockCompressor: <string> #集合数据压缩格式
# indexConfig:
# prefixCompression: <boolean> #启用索引的前缀压缩
# inMemory:
# engineConfig:
# inMemorySizeGB: <number>
有关生成mongo-key配置。可以参看这个url:https://www.huaweicloud.com/articles/716120f070b9defaba79ab083e59ff3a.html