mongodb权威指南读书笔记

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值