MongoDB简介

mongodb与mysql的对比

MySQL与MongoDB都是开源的常用数据库,但是MySQL是传统的关系型数据库,MongoDB则是非关系型数据库,也叫文档型数据库,是一种NoSQL的数据库。

关系型数据库-MySQL

1、在不同的引擎上有不同的存储方式。
2、查询语句是使用传统的sql语句,拥有较为成熟的体系,成熟度很高。
3、开源数据库的份额在不断增加,mysql的份额也在持续增长。
4、缺点就是在海量数据处理的时候效率会显著变慢。

非关系型数据库-MongoDB

非关系型数据库(nosql ),属于文档型数据库。先解释一下文档的数据库,即可以存放xml、json、bson类型的数据。这些数据具备自述性,呈现分层的树状数据结构。数据结构由键值(key=>value)对组成。

1、存储方式:虚拟内存+持久化。
2、查询语句:是独特的MongoDB的查询方式。
3、适合场景:事件的记录,内容管理或者博客平台等等。
4、架构特点:可以通过副本集,以及分片来实现高可用。
5、数据处理:数据是存储在硬盘上的,只不过需要经常读取的数据会被加载到内存中,将数据存储在物理内存中,从而达到高速读写。
6、成熟度与广泛度:新兴数据库,成熟度较低,Nosql数据库中最为接近关系型数据库,比较完善的DB之一,适用人群不断在增长。

MongoDB优势与劣势

优势:
1、在适量级的内存的MongoDB的性能是非常迅速的,它将热数据存储在物理内存中,使得热数据的读写变得十分快。
2、MongoDB的高可用和集群架构拥有十分高的扩展性。
3、在副本集中,当主库遇到问题,无法继续提供服务的时候,副本集将选举一个新的主库继续提供服务。
4、MongoDB的Bson和son格式的数据十分适合文档格式的存储与查询。
劣势:
1、 不支持事务操作。MongoDB本身没有自带事务机制,若需要在MongoDB中实现事务机制,需通过一个额外的表,从逻辑上自行实现事务。
2、 应用经验少,由于NoSQL兴起时间短,应用经验相比关系型数据库较少。
3、MongoDB占用空间过大。

数据库MongoDBMySQL
数据库模型非关系型关系型
存储方式以类JSON的文档的格式存储不同引擎有不同的存储方式
查询语句MongoDB查询方式(类似JavaScript的函数)SQL语句
数据处理方式基于内存,将热数据存放在物理内存中,从而达到高速读写不同引擎有自己的特点
成熟度新兴数据库,成熟度较低成熟度高
广泛度NoSQL数据库中,比较完善且开源,使用人数在不断增长开源数据库,市场份额不断增长
事务性仅支持单文档事务操作,弱一致性支持事务操作
占用空间占用空间大占用空间小
join操作MongoDB没有joinMySQL支持join

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MRESpU0h-1688838685531)(http://h9x14s4c.xyz/img/202112091927641.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cci20cxD-1688838685533)(http://h9x14s4c.xyz/img/202112091927125.png)]

语法对比:

https://www.cnblogs.com/mao2080/p/9570909.html

MongoDB安装

单机部署

window下:安装包安装或zip包解压使用

Linux下:apt安装或者tar包解压安装

[可选]修改配置文件

linux:在

/mongodb/single/mongod.conf

进行修改

参考:https://www.cnblogs.com/niumowangya/p/10422686.html

启动mongodb服务可指定配置文件方式启动,同redis

# 例如:
/usr/local/mongodb/bin/mongod -f /mongodb/single/mongod.conf

MongoDB连接

系统本地连接:

# 命令行形式连接
mongo
mongo --host=127.0.0.1 --port=27017
# 图形化界面客户端连接:
# 推荐使用compass或robo3t进行测试调试
# 连接方式:直接点击肉眼可见的连接,输入相关地址进行连接,方式极其简单

开发程序连接:

Java:

Go:

MongoDB常用命令

1、数据准备

1、MongoDB数据,工具为:Robo 3T

2、新增语句

方法说明语法备注
新增MongoDBdb.getCollection(‘user’).insert({“userId” : “014”,“uclass” : “B”,“name” : “Back”,“age” : 11,“email” : “b14@sina.com”,“birthday” : ISODate(“2018-07-31T03:46:13.885Z”),“dataStatus” : 1});
MySQLINSERT INTO sz-temp.user (userId, uclass, name, age, email, birthday, dataStatus) VALUES (‘014’, ‘B’, ‘Back13’, ‘20’, ‘b14@sina.com’, ‘2013-07-31 11:46:13’, ‘0’);

3、删除语句

方法说明语法备注
删除MongoDBdb.getCollection(‘user’).remove({“userId”:“014”});
MySQLdelete from user where userId = ‘014’;

4、修改语句

方法说明语法备注
修改MongoDBdb.getCollection(‘user’).update({“userId”:“013”}, {$set:{“email”:“b13@sina.com”, “age”:20}});
MySQLupdate user set email = ‘b13@sina.com’, age = 20 where userId = ‘013’;

5、查询语句

查询方法说明语法备注
查询所有MongoDBdb.getCollection(‘user’).find({});
MySQLselect * from user;
查询条件:=MongoDBdb.getCollection(‘user’).find({“uclass”:“A”});
MySQLselect * from user where uclass = ‘A’;
查询条件:likeMongoDBdb.getCollection(‘user’).find({“name”:/Ba/});
MySQLselect * from user where name like ‘%Ba%’;
查询条件:distinctMongoDBdb.getCollection(‘user’).distinct(“name”);
MySQLselect distinct uclass from user u;
查询条件:$gtMongoDBdb.getCollection(‘user’).find({“age”:{$gt:16}});greater than >
MySQLselect * from user where age >16;
查询条件:$gteMongoDBdb.getCollection(‘user’).find({“age”:{$gte:16}});gt equal >=
MySQLselect * from user where age >= 16;
查询条件:$ltMongoDBdb.getCollection(‘user’).find({“age”:{$lt:16}});less than <
MySQLselect * from user where age < 16;
查询条件:$lteMongoDBdb.getCollection(‘user’).find({“age”:{$lte:16}});lt equal <=
MySQLselect * from user where age <= 16;
查询条件:$neMongoDBdb.getCollection(‘user’).find({“age”:{$ne:16}});not equal !=
MySQLselect * from user where age != 16;
查询条件:$eqMongoDBdb.getCollection(‘user’).find({“age”:{$eq:16}});等效于:db.getCollection(‘user’).find({“age”:16});equal =
MySQLselect * from user where age = 16;
查询条件:inMongoDBdb.getCollection(‘user’).find({“uclass”:{$in:[‘A’, ‘B’]}});
MySQLselect * from user where uclass in (‘A’, ‘B’);
查询条件:andMongoDBdb.getCollection(‘user’).find({“uclass”:“B”, “age”:{$gt:16}});
MySQLselect * from user where uclass = ‘B’ and age > 16;
查询条件:orMongoDBdb.getCollection(‘user’).find({$or:[{“uclass”:“A”},{“class”:“B”}]});
MySQLselect * from user where uclass = ‘A’ or uclass = ‘B’;
查询条件:时间MongoDBdb.getCollection(‘user’).find({“birthday”:{$gt: new Date(“2008-08-14T06:24:40.110Z”), $lt: new Date(“2015-08-14T06:14:40.089Z”)}});
MySQLselect * from user where birthday > ‘2008-08-14 06:24:40’ and birthday < ‘2015-08-14 06:14:40’;
查询条数:countMongoDBdb.getCollection(‘user’).find({“uclass”:“A”}).count();
MySQLselect count(1) from user where uclass = ‘A’;
查询条件:sort升序MongoDBdb.getCollection(‘user’).find({}).sort({“age”:1});
MySQLselect * from user order by age asc;
查询条件:sort降序MongoDBdb.getCollection(‘user’).find({}).sort({“age”:-1});
MySQLselect * from user order by age desc;
聚合查询:count单列MongoDBdb.getCollection(‘user’).aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: group:{_id:"uclass",num:{$sum:1}}}]);
MySQLselect uclass, count(1) as num from user group by uclass;
聚合查询:count多列MongoDBdb.getCollection(‘user’).aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …:{_id:{uclass:"uclass", age:"KaTeX parse error: Expected 'EOF', got '}' at position 5: age"}̲,num:{sum:1}}}]);
MySQLselect uclass, age, count(1) as num from user group by uclass, age;
分页查询:limit nMongoDBdb.getCollection(‘user’).find({}).limit(5);查询前n条
MySQLselect * from user limit 5;
分页查询:limit m,nMongoDBdb.getCollection(‘user’).find({}).limit(5).skip(5);查询n条,从第m条开始
MySQLselect * from user limit 5,5;
查询指定字段MongoDBdb.getCollection(‘user’).find({}, {userId:1, name:1});第一个{}为查询条件
MySQLselect userId, name from user;
排查指定字段MongoDBdb.getCollection(‘user’).find({}, {dataStatus:0, _id:0});第一个{}为查询条件
MySQL

6、参考网站

http://www.runoob.com/mongodb/mongodb-aggregate.html

https://www.jianshu.com/p/5e870132ca7c

​ https://www.cnblogs.com/mao2080/p/9570909.html

//demo

一、删除数据
1.带条件删除
>db.user.remove({"name":"zhangshan"});
2.删除所有数据
>db.user.remove({})
3.删除集合
>db.user.drop()
4.删除整个数据库
>show dbs;
>db.user.getDB()
>db.dropDatabase()

****
#查看所有的collection(集合)
show collections 
#删除collection 
db.mail_addr.drop()

#删除当前的数据库  
db.dropDatabase()	

查找所有 
db.<CollectionName>.find([query])

使用官方可视化工具:mongodb compass

MongoDB常见问题说明

一些系统集合文档说明:

admin:

从权限的角度来看,这是root数据库。要是将一个用户添加到这个数据库中,这个用户自动继承所有数据库的权限。一些特定的服务端命令也只能从这个数据库运行,比如列出所有数据库或者关闭服务器。

local:

这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合。

config:

当Mongo用于分片设置时,config数据库库在内部使用,用于保存分片的相关信息。

集合的创建

显示创建:使用基本语法db.createCollection(name)进行创建

隐式创建:向一个集合中插入一个文档时候,如果集合不存在,则会自动创建集合

插入异常捕捉

使用try{}catch(e){}进行捕捉,如果遇到错误,则会打印错误信息

索引-index

索引支持MongoDB中查询的高效执行。如果没有索引,MongoDB必须执行集合扫描,即扫描集合中的每个文档,以选择与查询语句匹配的文档。如果查询存在适当的索引,MongoDB可以使用索引来限制它必须检查的文档数。

索引是特殊的数据结构[1],它以易于遍历的形式存储部分集合数据集。索引存储特定字段或字段集的值,按字段值排序。索引条目的排序支持高效的等值匹配和基于范围的查询操作。此外,MongoDB可以使用索引中的顺序返回排序后结果。

创建索引

使用db.collection.createIndex()

db.collection.createIndex( , )

例如创建单个键上的降序索引

db.collection.createIndex( { name: -1 } )

db.collection.createIndex方法仅用于创建索引,且相同定义的索引不存在

单字段索引

例如:在文档的单个字段上创建用户定义的升序/降序索引,称为单字段索引(single field index)

对于单个字段索引和排序操作,索引键的排序顺序(即升序或降序)并不重要,因为mongodb可以在任何方向上遍历索引。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lpmxnq9I-1688838685536)(http://h9x14s4c.xyz/img/202204031950015.png)]

复合索引

复合索引(compound index)中列出的字段顺序具有重要意义,例如:如果复合索引由{userid:1,score:-1}组成,则索引首先按userid正序排序,然后在每个userid的值内,再在score倒序排序。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WkO0BjIl-1688838685538)(http://h9x14s4c.xyz/img/202204031954951.png)]

其他索引

地理空间索引(geospatial index)、文本索引(text indexes)、哈希索引(hashed indexes)

地理空间索引(geospatial index)

为了支持对地理空间坐标数据的有效查询,mongodb提供了两种特殊的索引:返回结果时使用平面几何的二维索引和返回结果时使用球面几何的二维球面索引。

文本索引(text indexes)

mongodb提供了一种文本索引类型,支持在集合中搜索字符串内容。这些文本索引不存储特定于语言的停止词(例如:the、a、or),而将集合中的词作为词干,只存储根词。

哈希索引(hashed indexes)

为了支持基于散列的分片,mongodb提供了散列索引类型,它对字段值的散列进行索引。这些索引在其范围内的值分布更加随机,但只支持相等匹配,不支持基于范围的查询。

索引-index的基本操作

创建索引:

mongodb使用createIndex()和ensureIndex()方法来创建索引,前者用于3.0及以上版本,后者用于3.0以下版本。
语法:
db.COLLECTION_NAME.ensureIndex(keys[,options])
keys:要建立索引的参数列表。如:{KEY:1},其中key表示字段名,1表示升序排序,也可使用使用数字-1降序。
options:可选参数,表示建立索引的设置。可选值如下:
background,Boolean,在后台建立索引,以便建立索引时不阻止其他数据库活动。默认值为false。
unique,Boolean,创建唯一索引。默认值 false。
name,String,指定索引的名称。如果未指定,MongoDB会生成一个索引字段的名称和排序顺序串联。
partialFilterExpression, document.如果指定,MongoDB只会给满足过滤表达式的记录建立索引.
sparse,Boolean,对文档中不存在的字段数据不启用索引。默认值是 false。
expireAfterSeconds,integer,指定索引的过期时间

storageEngine,document,允许用户配置索引的存储引擎

db.users.createIndex({"name":1})
{
	"createdCollectionAutomatically" : false,
	"numIndexesBefore" : 1,
	"numIndexesAfter" : 2,
	"ok" : 1
}

例2:给name字段创建倒序索引

db.users.createIndex({"name":-1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 2,
"numIndexesAfter" : 3,
"ok" : 1
}

例3:给name,age字段创建组合索引

db.users.createIndex({"name":1,"age":1})
{
	"createdCollectionAutomatically" : false,
	"numIndexesBefore" : 3,
	"numIndexesAfter" : 4,
	"ok" : 1
}

例4:在后台给age字段创建索引

db.users.createIndex({age:1},{background:1})
{
	"createdCollectionAutomatically" : false,
	"numIndexesBefore" : 4,
	"numIndexesAfter" : 5,
	"ok" : 1
}

在后台创建索引的原因:
在前台创建索引期间会锁定数据库,会导致其它操作无法进行数据读写,在后台创建索引是,会定期释放写锁,从而保证其它操作的运行,但是后台操作会在耗时更长,尤其是在频繁进行写入的服务器上。

查看索引:

MongoDB提供的查看索引信息的方法:
getIndexes()方法可以用来查看集合的所有索引,
getIndexKeys()方法查看索引键。
totalIndexSize()查看集合索引的总大小,
getIndexSpecs()方法查看集合各索引的详细信息
例1: getIndexes()的用法

db.users.getIndexes()
[
	{
		"v" : 1,
		"key" : {
			"_id" : 1
		},
		"name" : "_id_",
		"ns" : "test1.users"
	},...
]

例2:getIndexKeys()的用法

db.users.getIndexKeys()
[
	{
		"_id" : 1
	},...
]

例3:totalIndexSize()的用法

db.users.totalIndexSize()
81920

例4:getIndexSpecs()的用法

db.users.getIndexSpecs()
[
	{
		"v" : 1,
		"key" : {
			"_id" : 1
		},
		"name" : "_id_",
		"ns" : "test1.users"
	},...
]

删除索引:

不再需要的索引,我们可以将其删除,mongodb提供两种删除索引的方法:
dropIndex()方法用于删除指定的索引
dropIndexes()方法用于删除全部的索引
例1:dropIndex()的用法

> db.users.dropIndex("name_1")
{ "nIndexesWas" : 5, "ok" : 1 }
> db.users.dropIndex("name_1_age_1")
{ "nIndexesWas" : 4, "ok" : 1 }
> db.users.getIndexSpecs()
...我们可以看到,name字段的索引和name与age字段的组合索引皆被删除

例2:dropIndexes()的用法

> db.users.dropIndexes()
{
	"nIndexesWas" : 3,
	"msg" : "non-_id indexes dropped for collection",
	"ok" : 1
}
> db.users.getIndexSpecs()
[
	{
		"v" : 1,
		"key" : {
			"_id" : 1
		},
		"name" : "_id_",
		"ns" : "test1.users"
	}
]
在使用了dropIndexes()方法后,我们之前建的所有索引都被删除掉了

索引重建:

我们之前把users的索引全部删除了,现在在name字段上建立一个正序索引,然后在name字段上重建倒序索引,可以看到重建索引是把之前name字段的索引删掉再新建一个索引的,重建之前name字段还是只有一个索引.

> db.users.createIndex({name:1})
{
	"createdCollectionAutomatically" : false,
	"numIndexesBefore" : 1,
	"numIndexesAfter" : 2,
	"ok" : 1
}
> db.users.getIndexSpecs()
[
	{
		"v" : 1,
		"key" : {
			"_id" : 1
		},
		"name" : "_id_",
		"ns" : "test1.users"
	},
	{
		"v" : 1,
		"key" : {
			"name" : 1
		},
		"name" : "name_1",
		"ns" : "test1.users"
	}
]
> db.users.reIndex({name:-1})
{
	"nIndexesWas" : 2,
	"nIndexes" : 2,
	"indexes" : [
		{
			"key" : {
				"_id" : 1
			},
			"name" : "_id_",
			"ns" : "test1.users"
		},
		{
			"key" : {
				"name" : 1
			},
			"name" : "name_1",
			"ns" : "test1.users"
		}
	],
	"ok" : 1
}
> db.users.getIndexSpecs()
[
	{
		"v" : 1,
		"key" : {
			"_id" : 1
		},
		"name" : "_id_",
		"ns" : "test1.users"
	},
	{
		"v" : 1,
		"key" : {
			"name" : 1
		},
		"name" : "name_1",
		"ns" : "test1.users"
	}
]

索引的使用

执行计划

分析查询性能(analyze query performance)通常使用执行计划(解释计划、explain plan)来查看查询的情况,如查询消耗的时间、是否基于索引查询等。

那么,通常我们知道,建立的索引是否有效,效果如何,都需要通过执行计划查看

一般使用在已建立索引的数据查询上,采用的是抓取查询,而不是全局扫描

db.collection.find(query.options).explain(options)

涵盖的查询(covered queries)

当查询条件和查询的投影仅包含索引字段时,mongodb直接从索引返回结果,而不扫描任何文档或将文档带入内存。这些覆盖的查询可以非常有效。

db.comment.find({userid:"1"},{userid:1,_id:0})

解释:当查询需要的值正好在索引上,那么mongodb则直接从索引中取值返回给用户,并不会进入到文档中进行搜索。

MongoDB集群和安全

副本集-replica sets

对于副本集,官方文档是这样定义的:副本集是一组mongod维护相同数据的实例,一个副本集包含多个数据承载节点和一个仲裁节点(可选),在数据承载节点中,只有一个成员节点被视为主节点,主节点能够进行读写操作,其它节点则被视为次要节点,次要节点只能进行读操作。

replica sets时一组维护相同数据集的mongod服务,副本集可提供冗余和高可用性,是所有生产部署的基础。

也可以说,副本集类似于有自动故障恢复功能的主从集群。通俗的讲就是多台机器进行同一数据的异步同步,从而使多台机器拥有同一数据的多个副本,并且当主库挂掉时在不需要用户干预的情况下自动切换其他的备份服务器做主库,而且还可以利用副本服务器做只读服务器,实现读写分离,提高负载

副本集的三个角色

副本集有两种类型三种角色

两种类型:

  • 主节点(Primary)类型:数据操作的主要连接点,可读写。
  • 次要(辅助、从)节点(Secondaries)类型:数据冗余备份节点,可以读或选举。

三种角色:

  • 主要成员(Primary):主要接收所有写操作。就是主节点
  • 副本节点(Replicate):从主节点通过复制操作以维护相同的数据集,即备份数据,不可写操作,但可以读操作(但需要要配置)。时默认的一种从节点类型。
  • 仲裁这(Arbiter):不保留任何数据的副本,只具有投票选举作用。当然也可以将仲裁服务器维护为副本集的一部分,即副本成员同时也可以是仲裁者。也是一种节点类型。

安全认证

…(待续)

点能够进行读写操作,其它节点则被视为次要节点,次要节点只能进行读操作。

replica sets时一组维护相同数据集的mongod服务,副本集可提供冗余和高可用性,是所有生产部署的基础。

也可以说,副本集类似于有自动故障恢复功能的主从集群。通俗的讲就是多台机器进行同一数据的异步同步,从而使多台机器拥有同一数据的多个副本,并且当主库挂掉时在不需要用户干预的情况下自动切换其他的备份服务器做主库,而且还可以利用副本服务器做只读服务器,实现读写分离,提高负载

副本集的三个角色

副本集有两种类型三种角色

两种类型:

  • 主节点(Primary)类型:数据操作的主要连接点,可读写。
  • 次要(辅助、从)节点(Secondaries)类型:数据冗余备份节点,可以读或选举。

三种角色:

  • 主要成员(Primary):主要接收所有写操作。就是主节点
  • 副本节点(Replicate):从主节点通过复制操作以维护相同的数据集,即备份数据,不可写操作,但可以读操作(但需要要配置)。时默认的一种从节点类型。
  • 仲裁这(Arbiter):不保留任何数据的副本,只具有投票选举作用。当然也可以将仲裁服务器维护为副本集的一部分,即副本成员同时也可以是仲裁者。也是一种节点类型。

安全认证

…(待续)

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐