MongoDB数据库基本操作

MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写,旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。

什么是NoSQL?

NoSQL,指的是非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称。NoSQL用于超大规模数据的存储。(例如谷歌或Facebook每天为他们的用户收集万亿比特的数据)。这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。

为什么使用NoSQL ?

今天我们可以通过第三方平台(如:Google,Facebook等)可以很容易的访问和抓取数据。用户的个人信息,社交网络,地理位置,用户生成的数据和用户操作日志已经成倍的增加。我们如果要对这些用户数据进行挖掘,那SQL数据库已经不适合这些应用了, NoSQL数据库的发展也却能很好的处理这些大的数据。

分布式系统

分布式系统(distributed system)由多台计算机和通信的软件组件通过计算机网络连接(本地网络或广域网)组成,是建立在网络之上的软件系统。正是因为软件的特性,所以分布式系统具有高度的内聚性和透明性。因此,网络和分布式系统之间的区别更多的在于高层软件(特别是操作系统)而不是硬件。分布式系统可以应用在在不同的平台上如:Pc、工作站、局域网和广域网上等。

RDBMS vs NoSQL

RDBMS

- 高度组织化结构化数据

- 结构化查询语言(SQL)

- 数据和关系都存储在单独的表中。

- 数据操纵语言,数据定义语言

- 严格的一致性

- 基础事务

NoSQL

- 代表着不仅仅是SQL

- 没有声明性查询语言

- 没有预定义的模式

-键 - 值对存储,列存储,文档存储,图形数据库

- 最终一致性,而非ACID属性

- 非结构化和不可预知的数据

- CAP定理

- 高性能,高可用性和可伸缩性

数据类型

下面为MongoDB中常用的几种数据类型:

1.object id:文档id

2.string:字符串,最常用,必须是有效的UTF-8

3.boolean:存储一个布尔值,true或false

4.integer:整数可以是32位或64位,这取决于服务器

5.double:存储浮点值

6.arrays:数组或列表,多个值存储到一个键

7.object:用于嵌入式的文档,即一个值为一个文档

8.null:存储null值

9.timestamp:时间戳

10.date:存储当前日期或时间的UNIX时间格式

(其中:object id:每个文档都有一个属性,为_id,保证每个文档的唯一性,可以自己去设置_id插入文档,如果没有提供,那么MongoDB为每个文档提供了一个独特的_id,类型为objectID是一个12字节的十六进制数,前4个字节为当前时间戳,接下来3个字节的机器ID,接下来的2个字节是MongoDB的服务进程id,最后3个字节是简单的增量值)。

数据库基本操作

1、数据库切换

db:查看当前数据库名称

show dbs:查看所有数据库名称,列出所有在物理上存在的数据库。

use 数据库名称:切换数据库,如果数据库不存在,则指向数据库,但不创建,直到插入数据或创建集合时数据库才被创建。

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

2、数据库删除

db.dropDatabase():删除当前指向的数据库,如果数据库不存在,则什么也不做

3、操作集合

db.createCollection('数据库名称',{capped:true,size:尺寸,max:1000}):在mongodb数据库中我们将类似于MySQL中的表的概念称为集合,将集合中每一行的记录称为文档,用此命令来创建集合,其中第二个参数可以不写,草capped表示是否指定该集合的尺寸,size表示该集合的具体尺寸是多少,max可以指定最大的文档个数。如果指定了集合的尺寸,我们可以想象其就像一个环形队列,当集合空间用完后,再插入的文档就会覆盖最初始的头部的文档!

show collections:查看当前数据库中所有的集合。

db.集合名称.drop():删除指定的集合

db.集合名称.insert({}):相向集合中插入数据,如果不指定_id字段,数据库会自动分配。

db.集合名称.find({},{}):查询集合中的文档,第一个字典参数为查询的条件,相当于MySQL中的where后面的条件,第二个字典参数为查询的结果显示哪些内容。均可为空或者不写,等效于db.集合名称.find(),默认查询出所有符合条件的文档。

db.集合名称.update({},{},{}):更新集合中的文档,第一个字典为要更新的文档的条件,第二个字典为更新的内容,第三个字典为时候全部更新,默认只会更新查询到的第一条文档。

可以看到按照上述的方式更新文档,会将查询到的文档除_id字段之外的所有字段都覆盖
使用$操作符进行更新时,不会进行覆盖而是进行追加,且在第三个参数不设置的情况下只会更新第一条文档
设置multi为true则会更新所有符合要求的文档

db.集合名称.save({}):保存文档,如果不指定_id字段或指定的_id字段在现有集合中没有,则会进行插入,相当于insert,如果已经有了,相当于更新,会阀盖之前的文档中的所有字段。

db.集合名称.remove({},{justOne:true或false}):删除符合条件的文档,默认为false即删除全部

db.集合名称.findOne({}):查询出符合条件的第一条文档。

比较运算符

‘:’等于,默认是等于判断,没有运算符

小于$lt  (less than)

小于或等于$lte (less than equal)

大于$gt 

大于或等于$gte (great than equal)

不等于$ne  (not equal)

逻辑运算符:,默认为与关系,$or为或关系

范围运算符:$in和$nin,表示的是单个的值,而不是连续的范围

正则表达式://或$regex

自定义查询:查询的条件可以是一个函数,且js中字符串的函数均可以使用。

limit和skip:limit指定读取文档的数量,skip指定跳过多少条文档,可以和find()配合使用,limit和skip没有先后顺序。

投影:在查询到的返回结果中,只选择必要的字段,而不是选择一个文档的整个字段

排序:sort(),1为升序,-1为降序

统计个数:count()

消除重复:distinct()

数据库高级操作

聚合

聚合操作aggregate类似于Linux和Unix中的管道命令‘|’,一般用于将当前命令的输出结果作为下一个命令的输入,如ps -aux | grep mongo,。在mongodb中,管道具有同样的作用,文档处理完毕后,通过管道进行下一次处理。

常用的管道如下:

$group:将集合中的文档分组,可用于统计结果

$match:过滤数据,只输出符合条件的文档

$project:修改输入文档的结构,如重命名、增加、删除字段、创建计算结果

$sort:将输入文档排序后输出

$limit:限制聚合管道返回的文档数

$skip:跳过指定数量的文档,并返回余下的文档

$unwind:将数组类型的字段进行拆分

常用表达式如下:

$sum:计算总和,$sum:1同count表示计数

$avg:计算平均值

$min:获取最小值

$max:获取最大值

$push:在结果文档中插入值到一个数组中

$first:根据资源文档的排序获取第一个文档数据

$last:根据资源文档的排序获取最后一个文档数据

$group():分组

$group中的键值对表示分组后每组会默认显示的字段

$match、$group、$project、$sort、$skip、$limit

$unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值

我们可以看到,集合中有很多条记录,但实际上只有最后一个记录包含有size这个字段且其是一个数组,接下来根据$size进行拆分:

可以看到其他不包含size字段的文档都丢失了,接下来拆分时再加上一个参数:

不包含size字段的数据并没有丢失

索引

索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构,其中存放的是集合中的部分字段和一些类似于地址一类的方便找到相应文档的地址的东西。

db.集合.ensureIndex({"列":1}):创建索引,1表示索引按升序存储,-1表示索引按降序方式存储。

db.集合.getIndexes():查询索引

db.集合.dropIndex({"列":1}):删除索引

db.集合.ensureIndex({"列":1},{unique":true}):唯一索引

db.集合.find().explain('allPlansExecution'):查看查询的详细过程。

在mongodb的collections中有一个默认存在的以_id为索引的内置索引,此索引不需要手动创建即可获取到:

db.集合.getIndexes():查询索引

db.集合名称.ensureIndex({'列':1或-1}):创建索引(1为升序排序,-1为降序排序)

看上这样一个集合,我们在没有手动创建索引的情况下,来看一下查询age为num14的文档的具体过程:

可以看到查询过程并,没有使用索引,且不得不对整个集合进行全盘扫描,一共查询了12条文档,查询时间虽然几乎是0,但是一旦数据量十分庞大,效率就十分不乐观了。

下面我们一age为索引来创建一个唯一索引:

1为升序排列,-1为降序排列

再来看一下搜索的过程:

可以看到在这样的情况下,只查询一条文档就查询到了所需的文档,虽然查询时间也是0,但数据量非常大时,和未建立索引的的查询效率对比就十分明显了。

db.集合名称.dropIndex({'列:1或-1'}):删除索引

索引限制:

1、额外开销

每个索引占据一定的存储空间,在进行插入,更新和删除操作时也需要对索引进行操作。所以,如果你很少对集合进行读取操作,建议不使用索引。

2、内存(RAM)使用

由于索引是存储在内存(RAM)中,你应该确保该索引的大小不超过内存的限制。如果索引的大小大于内存的限制,MongoDB会删除一些索引,这将导致性能下降。

3、查询限制

索引不能被以下的查询使用:

a、正则表达式及非操作符,如$nin, $not,等。

b、算术运算符,如$mod,等。

c、$where子句

4、索引键限制

从2.6版本开始,如果现有的索引字段的值超过索引键的限制,MongoDB中不会创建索引。

5、插入文档超过索引键限制

如果文档的索引字段值超过了索引键的限制,MongoDB不会将任何文档转换成索引的集合。与mongorestore和mongoimport工具类似。

6、最大范围

a、集合中索引不能超过64个

b、索引名的长度不能超过128个字符

c、一个复合索引最多可以有31个字段

安全

为了更安全的访问mongodb,需要访问者提供用户名和密码,于是需要在mongodb中创建用户,采用了角色-用户-数据库的安全管理方式。

在启用安全验证的情况下,需先修改配置文件,默认是不进行安全验证的,执行如下操作:

sudo  vim /etc/mongodb.conf

常用系统角色如下:

root:只在admin数据库中可用,超级账号,超级权限

read:允许用户读取指定数据库

readWrite:允许用户读写指定数据库

创建超级用户:

超级用户登录:sudo mongo -u 'xxx' -p '******' --authenticationDatabase 'admin'

创建普通用户:

普通用户登录:sudo mongo -u 'xxx' -p '******' --authenticationDatabase 'collection'

副本集

什么是复制

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

为什么要复制

a、数据备份

b、数据灾难恢复

c、读写分离

d、高(24* 7)数据可用性

d、无宕机维护

e、副本集对应用程序是透明

复制的工作原理

复制至少需要两个节点A、B...,A是主节点,负责处理客户端请求,其余的都是从节点,负责复制主节点上的数据。节点常见的搭配方式为:一主一从、一主多从,主节点记录在其上的所有操作,从节点定期轮询主节点获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致,主节点与从节点进行数据交互保障数据的一致性,只有主节点才能进行数据的增删改操作,从节点只能进行查询操作。

复制的特点

a、N个节点的集群

b、任何节点可作为主节点

c、所有写入操作都在主节点上

d、自动故障转移

e、自动恢复

模式一:主从复制

主从复制是MongoDB最常用的复制方式。这种方式非常灵活,可用于备份、故障恢复、读扩展等。

最基本的设置方式就是建立一个主节点和一个或者多个从节点,每个从节点要知道主节点的地址。

运行mongod --master就启动了主服务器,主服务器根据要求选取。

运行mongod --slave --source master_address则启动了从服务器,其中master_address就是上面主节点的地址。

下面来模拟主从复制:

创建三个文件夹来模拟三台服务器,在每个文件夹中分别包括一个db文件夹用来存放数据,log文件夹中的mongodb.log文件用来存放日志:

这样就启动了三台mongodb服务器,并在启动的时候确定了主机从机,在客户端连接不同的服务器时,采用 sudo mongo --host 'xxxxx' -- port 'xxxxx'的方式进行连接,因为模拟是在同一台机器上的,所以--host均为localhost,但在实际工作中,要根据具体情况而定。这样就实现了主从复制。

主从复制存在一个缺陷就是,如果主机宕机了,从机不会自动选举产生新的主机

模式二:副本集

在主从复制模式中,我们知道主机宕机之后,从机不会通过自动选举产生新的主机,而在设置副本集的模式中,则很好的解决了这一问题。在此模式中,启动服务器时不设置主从机,而是为几个服务器指定同一个副本集,第一个服务器在启动之后需要进行初始化,指定这个服务器群中都有哪些成员,每个成员的权重分别是多少,权重最高的设置为primary主机,其余的设置为secondry从机,当主机宕机时,成员会自动感应,并自动选举secondry中权重最高的为新的主机,假如宕机的主机又恢复正常,则这个主机就会重新称为primary,其他成员仍然为secondry,并且会与从机中的数据保持一致。

模拟一下副本集:创建的目录结构与主从复制相同,这里不再进行赘述。下面看一下具体操作:

第一台服务器启动之后的操作非常重要:

第一步:rs.slaveOk()

第二步:进行初始化:

第三步:查看状态:rs.status()  (不是必须的)

其他服务器不需要再进行初始化,但同样需要rs.slaveOk()等操作,与主从复制相同,只有primary可以进行增删改操作,secondry只能进行查询。

客户端连接的方式相同,同样采用sudo mongo -- host 'xxxx' --port 'xxxx'的方式

备份与恢复

备份:

语法:mongodump -h dbhost -d dbname -o dbdirectory

-h:服务器地址,也可以指定端口号

-d:需要备份的数据库名称

-o:备份的数据存放位置,此目录中存放着备份出来的数据

例1

sudo mkdir test1bak

sudo mongodump -h127.0.0.1:27017 -d test1 -o ~/Desktop/test1bak

恢复

语法:mongorestore -h dbhost -d dbname --dir dbdirectory

-h:服务器地址

-d:需要恢复的数据库实例

--dir:备份数据所在位置

例2

mongorestore -h 127.0.0.1:27017 -d test2 --dir ~/Desktop/test1bak/test1

mongodb与python进行交互

安装pymongo包:sudo pip install pymongo

下面简单实现一下增删改查操作:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容