mongo安装、卸载、备份、还原、分片、复制、监控、CRUD等操作

数据库系列


前言

MongoDB是当前最流行的数据库之一,属于文档型数据库。


一、为什么选择mongodb数据库?

MongoDB是当前最流行的数据库之一,属于文档型数据库,是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。它同时具备mysql和redis的特点(即持久化安全落盘写和异步不等落盘的快速写),还有很强大的内置分区、多副本和数据变更通知的功能。最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。

MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。

主要特点:
1、MongoDB 是一个面向文档存储的数据库,操作起来比较简单和容易。
2、你可以在MongoDB记录中设置任何属性的索引 (如:FirstName=“Sameer”,Address=“8 Gandhi Road”)来实现更快的排序。
3、你可以通过本地或者网络创建数据镜像,这使得MongoDB有更强的扩展性。
如果负载的增加(需要更多的存储空间和更强的处理能力) ,它可以分布在计算机网络中的其他节点上这就是所谓的分片。
4、Mongo支持丰富的查询表达式。查询指令使用JSON形式的标记,可轻易查询文档中内嵌的对象及数组。
5、MongoDb 使用update()命令可以实现替换完成的文档(数据)或者一些指定的数据字段 。
6、Mongodb中的Map/reduce主要是用来对数据进行批量处理和聚合操作。
7、Map和Reduce。Map函数调用emit(key,value)遍历集合中所有的记录,将key与value传给Reduce函数进行处理。
8、Map函数和Reduce函数是使用Javascript编写的,并可以通过db.runCommand或mapreduce命令来执行MapReduce操作。
9、GridFS是MongoDB中的一个内置功能,可以用于存放大量小文件。
10、MongoDB允许在服务端执行脚本,可以用Javascript编写某个函数,直接在服务端执行,也可以把函数的定义存储在服务端,下次直接调用即可。
11、MongoDB支持各种编程语言:RUBY,PYTHON,JAVA,C++,PHP,C#等多种语言。
12、MongoDB安装简单。

二、mongo基本功能

1.mongo安装与重要功能

你可以在mongodb官网下载该安装包,地址为:https://www.mongodb.com/download-center#community。

安装mongo 服务,客户端,备份(backup),恢复(restore)

准备好安装离线包,通过rpm -ivh安装
rpm -ivh mongo/cyrus-sasl-lib-2.1.26-23.el7.x86_64.rpm 
rpm -ivh mongo/cyrus-sasl-2.1.26-23.el7.x86_64.rpm 
rpm -ivh mongo/cyrus-sasl-gssapi-2.1.26-23.el7.x86_64.rpm
rpm -ivh mongo/cyrus-sasl-plain-2.1.26-23.el7.x86_64.rpm 
rpm -ivh mongo/mongodb-database-tools-100.5.1.x86_64.rpm 
rpm -ivh mongo/mongodb-org-database-tools-extra-4.4.3-1.el7.x86_64.rpm
rpm -ivh mongo/mongodb-org-server-4.4.3-1.el7.x86_64.rpm 
rpm -ivh mongo/mongodb-org-shell-4.4.3-1.el7.x86_64.rpm

systemctl enable mongod;             #建立systemctl服务管理
/bin/cp -f mongo/mongod.conf  /etc   
chmod 0644 /etc/mongod.conf
systemctl start mongod;              #启动mongodb


通过rpm -e卸载
rpm -e mongodb-org-server mongodb-org-shell
rpm -e mongodb-database-tools mongodb-org-database-tools-extra cyrus-sasl cyrus-sasl-gssapi cyrus-sasl-plain cyrus-sasl-lib
/bin/rm -rf /var/lib/mongo /etc/mongod.conf.rpmsave /var/log/mongodb
#数据默认存储目录为 /var/lib/mongo
#日志默认存储目录为 /var/log/mongodb/mongod.log
#数据存储大小默认 50G


mongo 单机开启副本集事务,初始化集群
mongo --host 127.0.0.1 --port 27017
use admin
rs.initiate({_id:"rs0",members:[{_id:0,host:"127.0.0.1:27017"},{_id:1,host:"127.0.0.1:27018"}]});
等价于
mongo --eval 'rs.initiate({_id:"rs0",members:[{_id:0,host:"127.0.0.1:27017"},{_id:1,host:"127.0.0.1:27018"}]})';

查看集群状态
rs.status()

查看副本集的配置
rs.conf()

关闭mongod
mongo --shutdown

安装成功后,可以通过mongo client 访问mongo server,端口默认27017,默认是没有用户的。

数据的备份与恢复

备份数据:
无用户数据备份
mongodump -d runoob -o /opt/app_backup/  
有用户数据备份
mongodump --authenticationDatabase admin -u admin -p admin -d runoob -o /opt/app_backup/  
恢复数据:
无用户数据恢复
mongorestore -d runoob /opt/app_backup/runoob 
有用户数据恢复
mongorestore -u admin -p admin --authenticationDatabase admin --drop -d runoob --dir /opt/app_backup/runoob 

MongoDB 复制(副本集)
MongoDB复制是将数据同步在多个服务器的过程。复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性, 并可以保证数据的安全性。复制还允许您从硬件故障和服务中断中恢复数据。

mongodb的复制至少需要两个节点。其中一个是主节点,负责处理客户端请求,其余的都是从节点,负责复制主节点上的数据。
mongodb各个节点常见的搭配方式为:一主一从、一主多从。
主节点记录在其上的所有操作oplog,从节点定期轮询主节点获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致。

创建conf,将mongodb.conf所有路径和port改成实际路径就行
mongo
rs.initiate({
     _id : "rs0",
     members : [
         {_id : 0, host : "192.168.31.223:27000"},
         {_id : 1, host : "192.168.31.164:27001"}
     ]
});

在这里插入图片描述
参考:https://blog.csdn.net/weixin_40863968/article/details/126631015
MongoDB的副本集与我们常见的主从有所不同,主从在主机宕机后所有服务将停止,而副本集在主机宕机后,副本会接管主节点成为主节点,不会出现宕机的情况。

mongostat 命令
mongostat是mongodb自带的状态检测工具,在命令行下使用。它会间隔固定时间获取mongodb的当前运行状态,并输出。如果你发现数据库突然变慢或者有其他问题的话,你第一手的操作就考虑采用mongostat来查看mongo的状态。

mongostat
mongostat -u admin -p 123456 --authenticationDatabase admin

参数解析:
inserts/s	每秒插入次数
query/s	    每秒查询次数
update/s	每秒更新次数
delete/s	每秒删除次数
getmore/s	每秒执行getmore次数,查看更多的意思,我们每次查询数据时,如果一次数据量比较大,超过了mongodb一次能查询的最大数据量,那么mongodb就回把这次要查询的数据分成几次查询,分别返回
command/s	每秒的命令数,比以上插入、查找、更新、删除的综合还多,还统计了别的命令
dirty	    WiredTiger存储引擎中dirty 数据占缓存百分比
used	    WiredTiger存储引擎中引擎使用缓存占百分比
flushes/s	每秒执行fsync将数据写入硬盘的次数, WiredTiger存储引擎中,flushes是指WiredTiger循环创建检查点的时间间隔。每隔一段时间,mongodb就将内存上的数据写入硬盘,如果这个数值比较大的话,会影响性能
vsize	    虚拟内存使用量,单位MB
res	        物理内存使用量,单位MB
faults /s	每秒访问失败数(只有Linux有),数据被交换出物理内存,放到swap。不要超过100,否则就是机器内存太小,造成频繁swap写入。此时要升级内存或者扩展
res	        使用真实内存大小
qr	        客户端等待读的长度,队列中的长度
qw	        客户端等待写的队列长度
ar	        活跃客户执行写操作的数量。
aw	        活跃客户等待写的数量
netin	    mongodb进入的流量包含mongostat本身(单位:bytes)
netout	    mongodb出去的流量包含mongostat本身
conn	    当前连接数
time	    时间戳

在这里插入图片描述

mongotop命令
mongotop也是mongodb下的一个内置工具,mongotop提供了一个方法,用来跟踪一个MongoDB的实例,查看哪些大量的时间花费在读取和写入数据。 mongotop提供每个集合的水平的统计数据。默认情况下,mongotop返回值的每一秒。

mongotop
mongotop -u admin -p 123456 --authenticationDatabase admin

在这里插入图片描述
mongo分片
在Mongodb里面存在另一种集群,就是分片技术,可以满足MongoDB数据量大量增长的需求。
当MongoDB存储海量的数据时,一台机器可能不足以存储数据,也可能不足以提供可接受的读写吞吐量。这时,我们就可以通过在多台机器上分割数据,使得数据库系统能存储和处理更多的数据。

分片重要主要组件:
Shard:用于存储实际的数据块,实际生产环境中一个shard server角色可由几台机器组个一个replica set承担,防止主机单点故障
Config Server:mongod实例,存储了整个 ClusterMetadata,其中包括 chunk信息。
Query Routers:前端路由,客户端由此接入,且让整个集群看上去像单一数据库,前端应用可以透明使用。
在这里插入图片描述
为什么使用分片
a)复制所有的写入操作到主节点
b)延迟的敏感数据会在主节点查询
c)单个副本集限制在12个节点
d)当请求量巨大时会出现内存不足。
e)本地磁盘不足
f)垂直扩展价格昂贵

Shard Server 127020
Shard Server 227021
Config Server :27100
Route Process:40000

启动Shard Server
mkdir -p /www/mongoDB/shard/s0
mkdir -p /www/mongoDB/shard/s1
mkdir -p /www/mongoDB/shard/log
mongod --port 27020 --dbpath=/www/mongoDB/shard/s0 --logpath=/www/mongoDB/shard/log/s0.log --logappend --fork
mongod --port 27021 -dbpath=/www/mongoDB/shard/s1 --logpath=/www/mongoDB/shard/log/s1.log --logappend --fork

启动Config Server
mkdir -p /www/mongoDB/shard/config
mongod --port 27100 --dbpath=/www/mongoDB/shard/config --logpath=/www/mongoDB/shard/log/config.log --logappend --fork

启动Route Process
mongos --port 40000 --configdb localhost:27100 --fork --logpath=/www/mongoDB/shard/log/route.log --chunkSize 500

配置Sharding即添加Shard节点
mongo admin --port 40000
db.runCommand({ addshard:"localhost:27020" })
db.runCommand({ addshard:"localhost:27021" })

db.runCommand({ enablesharding:"test" })       #设置分片存储的数据库
db.runCommand({ shardcollection: 'test.user', key: {name: 1}})

2.mongo的CRUD基本用法

创建数据库,默认的数据库为 test,如果你没有创建新的数据库,集合将存放在 test 数据库中
use databse

查看数据库
show dbs

插入数据库
db.databse.insert({"name":"菜鸟教程"})

删除数据库
use database
db.dropDatabase()

创建runoob集合类似于表
db.createCollection("runoob") 
show tables==show collections

创建固定集合mycol,整个集合空间大小 6142800 B, 文档最大个数为10000 个。
db.createCollection("mycol", { capped : true, autoIndexId : true, size : 
   6142800, max : 10000 } )

删除集合
use 
db.runoob.drop()

插入文档
db.runoob.insert({title: 'MongoDB 教程', 
    description: 'MongoDB 是一个 Nosql 数据库',
    by: '菜鸟教程',
    url: 'http://www.runoob.com',
    tags: ['mongodb', 'database', 'NoSQL'],
    likes: 100,
    date: 1667232000
})

查找表中所有文档
db.runoob.find()

查找数组中元素匹配
查下数组中每个doc中id为123且name为234的情况,其中id与name必须是同一个数组元素
db.runoob.find({"tags":{$elemMatch: {"id": "123", "name": "234"}}}) 
查下数组中doc中id为123且name为234的情况,其中id与name不一定是同一个数组元素
db.runoob.find({"tags.id":"123","tags.name":"234"}) 

更新文档
db.runoob.insert({
    title: 'MongoDB 教程', 
    description: 'MongoDB 是一个 Nosql 数据库',
    by: '菜鸟教程',
    url: 'http://www.runoob.com',
    tags: ['mongodb', 'database', 'NoSQL'],
    likes: 100
})

删除文档
db.runoob.remove({'title':'MongoDB 教程'})
或者删除文档
db.runoob.deleteOne({"_id":"123456"})
db.runoob.deleteMany({"dt":{$lt:1669913240}})
db.runoob.deleteMany({})
db.runoob.deleteMany({$or: [{"by":"菜鸟教程"}, {title":"MongoDB 教程"}]})  


查找文档(有些关键字可以查找其他文档比如gt,lt,or,and等)
#且查找
db.runoob.find({"by":"菜鸟教程", "title":"MongoDB 教程"}).pretty()
#或查找
db.runoob.find({$or: [{"by":"菜鸟教程"}, {title":"MongoDB 教程"}]}).pretty()     
#多条件查找
db.runoob.find({"likes": {$gt:50}, $or: [{"by": "菜鸟教程"},{"title": "MongoDB 教程"}]}).pretty() 
#多条件查找 发生时间100<ht<300内
db.runoob.find({"ht":{$gt:1668471207,$lt:1668478207}})
#查找,限制前100条的查找
db.runoob.find().limit(100)
#查找,限制为200条,其中前100条跳过
db.runoob.find().limit(200).skip(100)
#排序查找,其中1为升序排列,而 -1 是用于降序排列。
db.runoob.find().sort({"by":1})

方法distinct()对数据进行去重
查找时间>1671008764,不同的
db.runoob.distinct("name",{'dt':{$gt:1671008764}})

统计文档数
db.runoob.countDocuments({"dt":{$gt:1671033600,$lt:1671465600}})
db.runoob.count({"dt":{$gt:1671033600,$lt:1671465600}})
统计文档总数,无条件查询
db.runoob.estimatedDocumentCount()

统计大于ISO Date的文档
db.runoob.find({dt:{$gt:new Date('2022-11-21T10:29:14.089Z')}})	

创建索引
db.runoob.createIndex({"title":1})
db.runoob.createIndex({"title":1,"description":-1})

聚合操作,聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。
计算每个作者所写的文章数,每次+1
db.runoob.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}]) 


聚合操作,查找时间在[16672320001667923200]范围内,统计url为"http://www.runoob.com",每小时的数据量
其中:subtract表示减法,mod表示取余,用时间减去整数的余数,即可得到整数
db.getCollection('runoob').aggregate(
    {"$match":{"date": {'$gte':1667232000,'$lt':1667923200}},"url":"http://www.runoob.com"}},
    {"$group": {
        "_id": { "$subtract": ["$date",{ "$mod": ["$date",3600]}]},
        "total": {'$sum': 1}
    }}
)

参考:https://www.cnblogs.com/chuijingjing/p/16465404.html
聚合操作,查找时间在[16672320001667923200]范围内,_id以起始时间为基准开始统计,每3600为区间,统计url为"http://www.runoob.com",的数据量,输出_id、数量以及修正后的时间点,以datetime升降序进行排序输出
其中:subtract表示减法,mod表示取余,用时间减去整数的余数,即可得到整数
db.getCollection('runoob').aggregate(
    {"$match":{"date": {'$gte':1667232000,'$lt':1667923200},"url":"http://www.runoob.com"}}
	,{"$group": {
        "_id": { "$subtract": [
				{ "$subtract": [ "$date",  1667232000] },
                { "$mod": [{ "$subtract": [ "$date", 1667232000 ] },3600]}
			]},		
        "total": {'$sum': 1}
    }}
    ,{"$project": {
            "_id": 1,
            "count":1,
            'datetime': {'$add': [1667232000, '$_id']}                  
    }}
	,{"$sort": {
        'datetime': 1
    }}	
)
结果类似如下:
{ "_id" : 565200, "count" : 2, "datetime" : 1667797200 }
{ "_id" : 583200, "count" : 1, "datetime" : 1667815200 }


聚合操作,将runoob中tags中的数据拆分成多条数据
db.getCollection('runoob').aggregate([{$unwind:"$tags"}])

聚合统计,将runoob中files数据分成多条数据并查看文件类型为1或者2的数据总数
db.getCollection('runoob').aggregate(
[
	{"$unwind":"$files"},
	{"$match":{$or: [{"files.type": 1},{"files.type": 2}]}},
    {"$group": {
        "_id": "",
        "total": {'$sum': 1}
	}}	
])

统计某段时间内总文档数
db.runoob.aggregate(
   [
	  { $match: {"dt":{$gt:1671008765,$lt:1671008926}}},
      { $group: { _id: null, count: { $sum: 1 } } }
   ]
)

MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的。
表达式:处理输入文档并输出。表达式是无状态的,只能用于计算当前聚合管道的文档,不能处理其它的文档。
这里我们介绍一下聚合框架中常用的几个操作:
$project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
$match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
$limit:用来限制MongoDB聚合管道返回的文档数。
$skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
$unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
$group:将集合中的文档分组,可用于统计结果。
$sort:将输入文档排序后输出。
$geoNear:输出接近某一地理位置的有序文档。

展示title,author等字段
db.article.aggregate({ $project : {title : 1 ,author : 1 }});
db.article.aggregate({ $project : {_id : 0 ,title : 1 ,author : 1 }});

用于获取分数大于70小于或等于90记录,然后将符合条件的记录送到下一阶段$group管道操作符进行处理
db.articles.aggregate( [{ $match : { score : { $gt : 70, $lte : 90 } } },{ $group: { _id: null, count: { $sum: 1 } }}] );

前五个文档被"过滤"掉
db.article.aggregate({ $skip : 5 });

三、mongo高级功能

MongoDB GridFS
GridFS 用于存储和恢复那些超过16M(BSON文件限制)的文件(如:图片、音频、视频等)。
GridFS 也是文件存储的一种方式,但是它是存储在MonoDB的集合中。
GridFS 可以更好的存储大于16M的文件。
GridFS 会将大文件对象分割成多个小的chunk(文件片段),一般为256k/个,每个chunk将作为MongoDB的一个文档(document)被存储在chunks集合中。
GridFS 用两个集合来存储一个文件:fs.files与fs.chunks。
每个文件的实际内容被存在chunks(二进制数据)中,和文件有关的meta数据(filename,content_type,还有用户自定义的属性)将会被存在files集合中。

上传于下载mps文件

mongofiles -d gridfs put song.mp3    #上传mp3
mongofiles -d gridfs get song.mp3    #下载mp3
mongo
db.fs.files.find()
db.fs.chunks.find({files_id:ObjectId('534a811bf8b4aa4d33fdf94d')})

在这里插入图片描述

MongoDB 正则表达式
正则表达式是使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。
许多程序设计语言都支持利用正则表达式进行字符串操作。
MongoDB 使用 $regex 操作符来设置匹配字符串的正则表达式。

db.runoob.find({description:{$regex:"Nosql"}}) #正则表达式查找包含Nosql字符串的描述
db.runoob.find({post_text:{$regex:"Nosql",$options:"$i"}}) #且不区分大小写

引用式关系
引用式关系是设计数据库时经常用到的方法,这种方法把用户数据文档和用户地址数据文档分开,通过引用文档的 id 字段来建立关系。

#第一次查询用户地址的对象id(ObjectId),第二次通过查询的id获取用户的详细地址信息
var result = db.users.findOne({"name":"Tom Benzamin"},{"address_ids":1}) 
var addresses = db.address.find({"_id":{"$in":result["address_ids"]}})

MongoDB 覆盖索引查询

#第一次查询用户地址的对象id(ObjectId),第二次通过查询的id获取用户的详细地址信息
var result = db.users.findOne({"name":"Tom Benzamin"},{"address_ids":1}) 
var addresses = db.address.find({"_id":{"$in":result["address_ids"]}})

覆盖查询是以下的查询:a)所有的查询字段是索引的一部分 b)所有的查询返回字段在同一个索引中

#创建索引
db.users.createIndex({gender:1,user_name:1})
db.users.ensureIndex({gender:1,user_name:1})    #5.0版本后被移除
注意:当创建用户开启授权以后,就会出现创建索引阻塞的问题,解决办法如下:
openssl rand -base64 756 > /etc/mongod_keyfile;chmod 400 /etc/mongod_keyfile;chown mongod /etc/mongod_keyfile
//mongod.conf中security配置节添加keyFile选项
security: 
	keyFile: /etc/mongod_keyfile

db.users.find({gender:"M"},{user_name:1,_id:0}) 
对于上述查询,MongoDB的不会去数据库文件中查找。相反,它会从索引中提取数据,这是非常快速的数据查询。由于我们的索引中不包括 _id 字段,_id在查询中会默认返回,我们可以在MongoDB的查询结果集中排除它。

MongoDB 索引查询分析
MongoDB 查询分析可以确保我们所建立的索引是否有效,是查询语句性能分析的重要工具。
MongoDB 查询分析常用函数有:explain() 和 hint()。
mongodb提供db.collection.explain()、cursort.explain()及explain命令获取查询计划及查询计划统计信息。
利用explain命令,我们可以很好的观察系统如何使用索引来加快检索,同时可以做针对性的性能优化。
现版本explain有三种模式,分别是:queryPlanner、executionStats、allPlansExecution

//explain分析
db.users.find({"dt":{$gt:1671008765,$lt:1671008926},"number":200}).explain("executionStats")
db.users.find({"type":200}).explain("executionStats")
db.users.find({"type":100}).explain("executionStats")
db.users.explain().aggregate({ $project:{type : 1 }});
//强制索引
db.users.find({"dt":{$gt:1671008765},"name":{$regex:"沪"}}).hint({dt:-1,"name":1}).explain("executionStats")

主要参考3个返回项,nReturned、totalKeysExamined、totalDocsExamined,分别表明该条查询返回的条目、索引扫描条目、文档扫描条目。这些都是直观地影响到executionTimeMillis,咱们须要扫描的越少速度越快。
对于一个查询,咱们最理想的状态是:nReturned=totalKeysExamined=totalDocsExamined

explain中关注的是COLLSCAN、IXSCAN、keysExamined、docsExamined 等关键字,keysExamined 和 docsExamined 越大代表没有建索引或者索引的区分度不高。
1、COLLSCAN:代表该查询进行了全表扫描;
2、IXSCAN:代表进行了索引扫描;
3、keysExamined:代表索引扫描条目;
4、docsExamined:代表文档扫描条目。
5、nReturned:获胜计划(winning plan)完整的查询执行数据
6、executionTimeMillis:查询条件匹配到的文档数量

MongoDB官方提供的分析命令,详情请参见:
通过MongoDB自身提供的命令db.stats()和db.$collection_name.stats()分析。

db.stats()
db.collection.stats()
db.collection.storageSize()
db.collection.totalIndexSize()
db.collection.totalSize()

MongoDB 固定集合
MongoDB 固定集合(Capped Collections)是性能出色且有着固定大小的集合,对于大小固定,我们可以想象其就像一个环形队列,当集合空间用完后,再插入的元素就会覆盖最初始的头部的元素!

属性
属性1:对固定集合进行插入速度极快
属性2:按照插入顺序的查询输出速度极快
属性3:能够在插入最新数据时,淘汰最早的数据
用法
用法1:储存日志信息
用法2:缓存一些少量的文档

#我们通过createCollection来创建一个固定集合,且capped选项设置为true:
db.createCollection("cappedLogCollection",{capped:true,size:10000})
#还可以指定文档个数,加上max:1000属性:
db.createCollection("cappedLogCollection",{capped:true,size:10000,max:1000})
#判断集合是否为固定集合:
db.cappedLogCollection.isCapped()
#如果需要将已存在的集合转换为固定集合可以使用以下命令:
db.runCommand({"convertToCapped":"mycoll",size:10000})
#固定集合文档按照插入顺序储存的,默认情况下查询就是按照插入顺序返回的,也可以按照$natural调整返回顺序
db.cappedLogCollection.find().sort({$natural:-1})

MongoDB 原子操作
mongodb提供了许多原子操作,比如文档的保存,修改,删除等,都是原子操作。
所谓原子操作就是要么这个文档保存到Mongodb,要么没有保存到Mongodb,不会出现查询到的文档没有保存完整的情况。

MongoDB ObjectId
ObjectId 是一个12字节 BSON 类型数据,有以下格式:
前4个字节表示时间戳
接下来的3个字节是机器标识码
紧接的两个字节由进程id组成(PID)
最后三个字节是随机数。
MongoDB中存储的文档必须有一个"_id"键。这个键的值可以是任何类型的,默认是个ObjectId对象。
在一个集合里面,每个文档都有唯一的"_id"值,来确保集合里面每个文档都能被唯一标识。
MongoDB采用ObjectId,而不是其他比较常规的做法(比如自动增加的主键)的主要原因,因为在多个 服务器上同步自动增加主键值既费力还费时。

newObjectId = ObjectId()
ObjectId("5349b4ddd2781d08c09890f4").getTimestamp()
new ObjectId().str

MongoDB 全文检索
全文检索对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。
全文检索要用到” t e x t “判断符,而想要进行数据的查询则使用” text“判断符,而想要进行数据的查询则使用” text判断符,而想要进行数据的查询则使用search“运算符

db.posts.createIndex({post_text:"text"})      #创建索引
db.posts.find({$text:{$search:"runoob"}})     #查询
db.posts.getIndexes()                         #获取索引
db.posts.dropIndex("post_text_text")          #删除索引

Map Reduce
Map-Reduce是一种计算模型,简单的说就是将大批量的工作(数据)分解(MAP)执行,然后再将结果合并成最终结果(REDUCE)。
略,后面补上

基于地理位置查询
支持4种查询:geoIntersects geoWithin near nearSphere
GeoJSON对象类型:Point,LineString,Polygon,MultiPoint,MultiLineString,MultiPolygon,GeometryCollection
经度范围[ -180,180]
纬度范围[ -90,90]
< field >: { type: < GeoJSON type> , coordinates: < coordinates > }
Polygon:闭合线至少有四个坐标对,并指定与第一个和最后一个坐标相同的位置。

MongoDB提供地理空间索引类型以支持地理空间查询。只支持2维坐标
遵循格式:
location: { type: “Point”, coordinates: [ 0, 0] }
db.collection.createIndex( { location field : “2dsphere” } )
参考:https://www.fengjinwei.com/blog-1217144.html

基于圆形查询
use places
db.places.insertMany( [
   {
      name: "Central Park 1",
      location: { type: "Point", coordinates: [ 1, 1 ] },
      category: "Parks"
   },
   {
      name: "Sara D. Roosevelt Park 1",
      location: { type: "Point", coordinates: [ 2, 2 ] },
      category: "Parks"
   },
   {
      name: "Polo Grounds 1",
      location: { type: "Point", coordinates: [ 3, 3 ] },
      category: "Stadiums"
   }
] )
创建索引
db.places.createIndex( { location: "2dsphere" } )

基于圆形查询:
//100000为m,1609m对应1mile,地球半径3963.2mile,转换为弧度
db.places.find( {location: { $geoWithin: { $centerSphere: [ [ 1, 1 ], (100000/1609)/3963.2 ] } }} )



基于点的区域查找
db.places.find({
     location:
       { $near:{
            $geometry: { type: "Point",  coordinates: [ 1, 1 ] },
            $minDistance: 0,
            $maxDistance: 1
          }
       }
})

基于多边形查询,注意首点、尾点一定要重合,不然会报错
db.places.find({
	location:
	{$geoWithin:
		{          
			$geometry:{type:"Polygon",coordinates:[[[0,2],[2,2],[2,0],[0,0],[0,2]]]}
		}
	}
})

基于点,判断是否在多边形区域内部还是外部,前提是已经存在区域
db.places.find({
	polygons:
	{
		$geoIntersects:{
			$geometry:{ "type" : "Point","coordinates" : [1.1,1.1] }}
		}
});

基于矩形查询
db.places.find( {
   location: { $geoWithin: { $box:  [ [ 0, 0 ], [ 2, 2] ] } }
} )

模糊查找

use test
db.test.find()
{ "_id" : "3CEA2E755178", "topic" : "监控机场" }
{ "_id" : "4CEA2E755179", "topic" : "监控机场" }

//两种方式模糊查找
db.test.find({_id:{$regex:"3CEA2"}})
{ "_id" : "3CEA2E755178", "topic" : "监控机场" }
db.test.find({_id:/3CEA2E7/})
{ "_id" : "3CEA2E755178", "topic" : "监控机场" }

//不区分大小写
db.test.find({"_id":{"$regex":"3ce", "$options": "-i"}})
{ "_id" : "3CEA2E755178", "topic" : "监控机场" }

//首尾不填,中间未知填*,*表示0次(含)以上
db.test.find({_id:/A2E75*17/})   == db.test.find({_id:/A2E755*17/})
{ "_id" : "3CEA2E755178", "topic" : "监控机场" }
{ "_id" : "4CEA2E755179", "topic" : "监控机场" }
db.test.find({_id:{$regex:"A2E75*17"}})
{ "_id" : "3CEA2E755178", "topic" : "监控机场" }
{ "_id" : "4CEA2E755179", "topic" : "监控机场" }

//首尾不填,中间重复5+,+表示1次(含)以上
rs0:PRIMARY> db.test.find({_id:/5+/})
{ "_id" : "3CEA2E755178", "topic" : "监控机场" }
{ "_id" : "4CEA2E755179", "topic" : "监控机场" }

 
//首尾不填,中间未知填?,?表示0次或1次,但是db.test.find({_id:/EA?/}) 不支持
db.test.find({_id:{$regex:"EA?"}})
db.test.find({_id:{$regex:"EA?2E"}})
{ "_id" : "3CEA2E755178", "topic" : "监控机场" }
{ "_id" : "4CEA2E755179", "topic" : "监控机场" }

三、mongo 常见问题解决

问题1:安装配置完成后尝试启动mongod进程,出现了“Process: **ExecStart=/usr/bin/mongod $OPTIONS (code=exited, status=14)”错误。经过一番探索,发现这是文件权限问题,用户mongod没有对必需文件的写权限,导致数据库服务不能启动。
sudo chown -R mongod:mongod /var/lib/mongo
sudo chown -R mongod:mongod /var/log/mongodb
sudo chown mongod:mongod /tmp/
.sock
重启mongod

问题2:创建用户名开启授权后,创建索引会阻塞
解决办法:启用一下mongodb成员之间的keyfile认证
1,生成随机的keyfile文件
openssl rand -base64 756 > /etc/mongod_keyfile;chmod 400 /etc/mongod_keyfile;chown mongod /etc/mongod_keyfile
2,mongod.conf中security配置节添加keyFile选项
security:
keyFile: /etc/mongod_keyfile

问题3:关于mongodb占用内存过大的问题
未设置cacheSizeGB的情况下:系统内存与默认内存 两者取较大的来使用
系统内存,会使用到(系统内存-1GB)/2。
默认内存:使用256MB(老版本是1G,后来为了照顾小机器下调了)

主要是看storage.wiredTiger.engineConfig.cacheSizeGB,这个参数设置的是wiredTiger引擎可以使用内存的大小,
mongo在3.2的版本之前,默认引擎是MMAP,3.2版本之后,默认的是wiredTiger,因为我们的版本是4.4.2,所以就不从引擎区别上去深究了。

wiredTiger在插入的时候内存一直控制在限制之内。但在做查询或者做删除的时候,wiredTiger是限制不了内存的,内存还会上涨。
mongo的机制有点无赖,只向操作系统要内存,而不会管理内存,比较依赖系统自身的内存淘汰算法,所以我们经常能看到内存占用过高的表现。
如果集合数据量大,而索引设置的不对,也会造成内存占用超高,因为结果集都被扔到了内存。

问题4:如何判断mongo内存占用情况
通过db.serverStatus().wiredTiger.cache可以来判断内存的使用情况
重点关注五个指标:

db.serverStatus().wiredTiger.cache['maximum bytes configured']
db.serverStatus().wiredTiger.cache['bytes currently in the cache']
db.serverStatus().wiredTiger.cache['tracked dirty bytes in the cache']
db.serverStatus().wiredTiger.cache['pages written from cache']
db.serverStatus().wiredTiger.cache['pages read into cache']

rs0:PRIMARY> db.serverStatus().wiredTiger.cache['maximum bytes configured'] 16246636544 
rs0:PRIMARY> db.serverStatus().wiredTiger.cache['bytes currently in the cache']
978992763 
rs0:PRIMARY> db.serverStatus().wiredTiger.cache['tracked dirty bytes in the cache'] 1307942 
rs0:PRIMARY> db.serverStatus().wiredTiger.cache['pages written from cache'] 243141
rs0:PRIMARY> db.serverStatus().wiredTiger.cache['pages read into> cache'] 10920

使用情况:

use test
db.stats(1073741824)


rs0:PRIMARY> db.stats(1073741824)
{
        "db" : "vtollgate",
        "collections" : 2,
        "views" : 0,
        "objects" : 1463204,
        "avgObjSize" : 342.00221226841916,
        "dataSize" : 0.466051516123116,
        "storageSize" : 0.09939193725585938,
        "indexes" : 4,
        "indexSize" : 0.14574432373046875,
        "totalSize" : 0.24513626098632812,
        "scaleFactor" : 1073741824,
        "fsUsedSize" : 31.342559814453125,
        "fsTotalSize" : 497.94922256469727,
        "ok" : 1,
        "$clusterTime" : {
                "clusterTime" : Timestamp(1671367446, 1),
                "signature" : {
                        "hash" : BinData(0,"P9PmqISHpTKaid+BKl/yx7ye3k8="),
                        "keyId" : NumberLong("7176641827628384260")
                }
        },
        "operationTime" : Timestamp(1671367446, 1)
}

查看单表占用
db.test.stats(1073741824)

问题5:如何设置mongodb的缓存
方法一:
修改配置文件mongod.conf
添加内容如下

storage:
  dbPath: /data/db
  journal:
    enabled: true      #启用journal日志,false为关闭   注意:这里应该是4个空格。
  engine: wiredTiger    #指定存储引擎             注意:这里应该是2个空格。
  wiredTiger:                            注意:这里应该是2个空格。
    engineConfig:       #存储引擎的配置           注意:这里应该是4个空格。
      cacheSizeGB: 4     #来指定mongodb使用内存的多少-8G  注意:这里应该是6个空格。

方法二:
直接登mongo修改

db.adminCommand( { "setParameter": 1, "wiredTigerEngineRuntimeConfig": "cache_size=1G"})
db.serverStatus().wiredTiger.cache['maximum bytes configured']/1024/1024/1024

问题6:如何检测mongo状态

db.serverStatus()

总结

本文主要讲解了mongodb的linux服务器上的安装,基本功能,使用,后面文章会讲解c++来实现mongo的crud功能。

老铁:如果觉得海不错,别忘了随手点赞转发+关注哦!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

c+猿辅导

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值