1.软文推荐

2.软文推荐

3.软文推荐

MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。

MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型,本篇文章重点为大家讲解一下MongoDB的CRUD操作。

INSERT操作

MongoDB中的新增操作,把一个新的Document插入到一个Collection中。

如果该Collection不存在,则新增一个新的Collection。这个和关系数据库有很大的区别,在关系数据库中,我们需要定义数据库的schema和表结构,这是NoSQL(MongoDB是NoSQL的一种)数据库和关系数据库很大的区别。在MongoDB中,我们可以在一个Collection中包含多个不同结构的Document(不推荐这样做,一个Collection最好具有相同格式的Document,便于维护和使用)。

关于”*id”字段,当我们新增一个Document到Collection中的时候,MongoDB需要每一个新增的Document中有一个”*id”字段,MongoDB把这个字段作为主键,所以要求这个字段在Collection中是唯一的。如果新增的Document中没有包含”*id”字段,那么MongoDB的客户端会在该Document中新增一个值为ObjectId类型的”*id” 字段;如果MongoDB服务在新增Document的时候发现Document中没有”*id”字段,那么mongod会新增一个值为ObjectId类型的”*id”字段到该Document中。

MongoDB对单个Document的写操作是原子的。

MongoDB提供了如下的方式来进行新增操作:

db.collection.insert()
db.collection.insertOne() 3.2版本新增
db.collection.insertMany() 3.2版本新增
db.collection.insert()

insert操作可以新增单个Document,也可以新增多个Document。如果新增单个Document,则把需要新增的Document作为参数传递给insert(),如果新增多个Document,则将多个Document的数组作为参数传递个insert()函数。

比如我们需要在”post”这个collection上新增一个Document来表示我们的博客中新增了一篇文章,我们可以这么做:

现在,我们给post这个Collection新增了一个Document,表示在Blog中新增了一篇文章。我们可以看下现在post这个Collection中是不是有我们新增的Document。

这里我们使用findOne()来查询,我们可以看到,我们由于没有在Document中包含”*id”字段,所以MongoDB自动为我们新增了一个”*id”字段。

insert()函数可以一次新增多个Document,只要将一个Document的数组传递给insert()就可以了,如:

db.collection.insertOne()

insertOne()函数是在3.2版本中新增的,它用来添加单个Document。例子如下:

db.collection.insertMany()

insertMany()函数是insert的批量增加的版本,支持一次新增多个Document,它也是3.2版本中新增的函数:

好了,我们简单介绍了下insert操作的三个函数,下面,我们已经在MongoDB的数据库里新增了几个Document了。接下来,是时候开始学习查找操作来查看这些已经存储在MongoDB的记录了。

QUERY操作

MongoDB提供了db.collection.find()函数来执行查询操作,函数将返回一个游标(cursor),用于遍历查询到的Documents。find()函数接受两个参数,一个是过滤条件,还有一个是投影。

db.collection.find(  )
用于查找满足过滤条件的Document
(投影)用于指定被找到的Document中需要返回哪些字段,用于限制网络中传输的数据的大小。投影的概念和关系数据库中的投影的概念基本是一致的。

现在,我们可以查询下刚才我们新增的所有的Documents,通过find(),我们来看下如何查询:

如果我们没有传递任何参数,或者传递一个”{}”给find()函数,那会find()返回Collection中所有的Document。现在,可以看到我们刚才新增的所有的Documents。

接下来,我们通过指定条件,查询标题为”Third Post”的Document,我们可以这样做:

发现了么,我们的查询条件其实就是以Document方式构造的。在MongoDB中,我们可以通过构造不同的Document来定义不同的查询条件。

除了使用具体的字段来过滤,我们还可以使用查询操作符来做更加灵活的操作。我们现在需要查找出标题是”Third Post”或”Fifth Post”这两篇Post中的任何一篇,我们可以使用**$in**操作符来查询:

除了使用**,还提供了很多有用的操作符来帮助构造过滤条件,如lt**, and, $or等。

使用子Document中值作为过滤条件

现在,我们假设有一篇文章,在Document中的存储如下:

现在,我们需要匹配内部Document中的条件,比如我们需要查找author中name是Duke的记录,我们可以这样构造我们的筛选条件:

db.post.findOne(
{
"author":
{
"name""Duke",
"email""740313507@qq.com"
}
})

查询结果就是这样的

我们观察这个过滤条件,发现和上面的过滤条件的结构一样,就是{“field”:”value”}的格式,只是不同的是,这次的”value”不再是一个普通的值了,而是一个Document。通过这种方式来过滤,具有一些局限性,我们如果要查找author中name是Duke的记录,我们必须完整指定author的值,也就是需要完整的Document。如果需要只过滤name,而不关系email的值,我们可以这样构造过滤条件:

db.post.findOne({"author.name""Duke"})

查询到和上面一样的结果

但是,这次我们使用了”author.name”的方式来指定field。这种类似于成员引用的”点符号”结构的查询,可以用来对内嵌的Document中的指定的field进行过滤。后面你将会看到,对于数组类型的值,也可以通过类似的方式来构造过滤条件。

使用数组中的元素作为过滤条件

接下来我们看下如何使用数组中的值来构造过滤条件。最简单的,也是最容易想到的,就是把整个数组作为过滤条件,类似于上面的把整个子Document作为过滤条件一样,我们可以这样构造

db.post.findOne({"comments": ["comment one""comment two"]})

查询的结果如下:

但是,这种方式没法指定数组中的某个值作为过滤件。如果要使用数组中的某个值作为过滤条件,我们可以这么构造过滤条件:
db.post.find({"comments""comment two"})

查询到的结果如下:

这里最后使用了”pretty()”方法来格式化输出,输出格式化的数据,便于观察,仅此而已,没有别的用途。我们可以看到,这种方式构造的过滤条件,使用了数组中的一个元素来筛选记录,只要数组中包含了这个元素(不管这个元素的下标),那么就会过滤出这条记录,有点像集合中的in操作。这种方式可以匹配数组中的一个元素。

接下来,我们更近一步,我们需要匹配数组的某一个下标位置的元素,那么我们需要使用上面一开始提到的,使用类似匹配子Document的那种成员引用(点符号)方式来构造过滤条件:

db.post.find({"comments.0""comment two"})

查询到的结果如下:

这里,我们使用{“comments.0”: “comment two”}的方式指定匹配的条件是:数组”comments”下标为0的位置的值为”comment two”。这样,就可以过滤掉之前下标为1的位置为”comment two”的记录了。可以看出,在使用数组下标构造过滤条件的时候,下标是从0开始的。

MongoDB提供了丰富的操作符来支持构造灵活的过滤条件,这里就先介绍这么点。由于篇幅关系,这里就不再展开了,下次独立写篇文章重点介绍下MongoDB中的查询操作。接下来,我们该看下如何在MongoDB中进行更新操作。

UPDATE操作

MongoDB也支持基本的更新操作,它提供了4个用于更新的方法:

db.collection.updateOne() 3.2版本新增
db.collection.updateMany() 3.2版本新增
db.collection.update()
db.collection.replaceOne() 3.2版本新增

这些Update方法支持三个参数:

用于筛选记录的过滤条件,过滤出需要被更新的记录,过滤条件和query中使用的过滤条件类似。
一个新的Document,用于更新部分值或者替换除了”_id”之外的一整个Document。
一个以Document格式组织的一组更新选项。

MongoDB对于单个Document的更新操作是原子的。 MongoDB在更新时对于”*id”主键的处理原则是,不管是更新还是替换Document,都不能更改被更新的Document的”*id”主键,如果在替换的时候包含了不同的”_id”,那么替换会失败,如:

上面的例子中,我们修改了原先的”*id”值为1,然后进行替换更新,发现更新失败,提示”*id”值不能被更改。

当我们更新的时候,新的Document的大小超过了原先旧的Document的大小的时候,更新操作会重新申请一块更大的空间来存放这个新的Document。

接下来,我们来看下这些更新API的用法。

db.collection.updateOne()

updateOne()函数是在3.2版本中新增的一个API,用于更新一条匹配到的Document。现在我们需要更新我们的Post集合中的标题为”First Post”的Document,我们想增加一些评论,我们可以这么构造我们的更新表达式:

db.post.updateOne({"title""First Post"}, {"$set": {"comments": ["comment one"]}})

现在,我们的”First Post”这篇文章就有了一条评论了。这里我们使用”$set”操作符来设置一个新的字段,MongoDB的更新操作提供了一些有用的操作符来帮助构造更新语句。updateOne()函数会更新第一个被匹配到的Document。如果要更新多个Document,我们可以用updateMany()函数来支持。

db.collection.updateMany()

updateMany()函数可以对匹配到的所有的Document进行更新操作。比如我们想更新所有的文章,让每篇文章都有一个浏览数的字段,表示别浏览的次数。我们可以这样做:

db.post.updateMany({}, {"$set": {"view": 0}})

我们可以看到,通过updateMany()函数,我们更新了所有的Document,使得每个Document都包含了一个”view”字段,初始值为0。

替换Document

上面提到了两个API,都是对Document中的某个字段进行更新。它们除了可以对Document中的单个字段进行更新外,还可以对匹配到的整个Document进行替换(除了”*id”属性外,可以替换任何属性)。只要把更新参数改成一个普通的Document(Document的结构中不包含操作符),就可以对匹配到的Document替换成参数中的Document。进行Document替换更新的时候,需要注意:原先的Document中的”*id”属性是不能被更改的,所以新的用于替换的Document不能包含”*id”属性,如果包含了”*id”属性,那么这个”*id”属性必须是和被更新的Document的”*id”属性是相同的。

除了上面的两个API可以用于替换Document,MongoDB在3.2版本中新增了一个replaceOne()函数来进行替换操作。现在我们用replaceOne()来替换一个Document,我们把”title”是”First Post”的Document替换成新的Document:

db.post.replaceOne({"title""First Post"}, {"title""New Post""content""new content""create_time": new Date()})

现在,我们已经把”title”为”First Post”的Document替换为了新的”title”为”New Post”的Document了。

最后,我们来看下上面三个API的集大成者,就是update()函数,它基本包含了上面提到的三个API的所有功能,默认情况下,update()函数会更新匹配到的第一个Document,如果设置了”multi”选项,那么就可以更新匹配到的所有的Document。

下面我们使用update()来更新匹配到的第一个Document:

db.post.update({"title""New Post"}, {"$set": {"view": 0}})

好了,更新操作介绍到这里,接下来就是最后一个删除操作了。

DELETE操作

到这里,我想大家都已经了解了MongoDB中的”增”,”改”,”查”的功能了,接下来我们来看下”删”这个功能。MongoDB提供了三个用于删除操作的API,分别是:

db.collection.deleteOne()
db.collection.deleteMany() 3.2版本新增
db.collection.remove() 3.2版本新增

这三个API都支持一个过滤条件参数,用于匹配到满足条件的Document,然后进行删除操作。

从三个API的字面意思我们可以看出,deleteOne()会删除匹配到的所有的Document中的第一个,而deleteMany()和remove()会删除所有匹配到的Document。

假设我们需要删除”title”为”New Post”的Document,我们可以用deleteOne()来操作

db.post.deleteOne({"title""New Post"})

当删除了”title”为”New Post”的Document以后,我们再次去查询的时候,发现这个Document确实已经被删除了。deleteOne()用于删除单个Document,如果我们需要删除所有满足过滤条件的Document的话,我们可以用deleteMany()或者remove()来实现。

现在我们想删除所有浏览数为0的文章,那么我们可以用deleteMany()或者remove来实现:

db.post.remove({"view": 0})

由于我们存储在集合中的所有Document的view值都是0,所以上面的操作相当于我们清空了我们的Collection。

本文来源:www.lxlinux.net/8584.html,若引用不当,请联系修改。

相关文章 8

1

免费申请虚拟主机(虚拟主机开通) 2分钟前

目录:1、如何申请免费虚拟主机2、蓝队云免费虚拟主机怎么申请领取?3、虚拟主机怎样申请?4、虚拟主机如何开通?如何申请免费虚拟主机...

2

ubuntu部署ubuntu 3分钟前

Supervisor是用Python开发的一套通用的进程管理程序,能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出时能自动重启。它...

4

cn2是什么意思(宫颈cn2是什么意思) 7分钟前

目录:1、香港服务器的cn2是什么意思?2、什么是CN2网络?3、服务器中的CN2线路是什么意思?香港服务器的cn2是什么意思? CN2全称为中国电...

5

Linux安装Apache服务器 10分钟前

Linux系统如何安装Apache服务器? Apache (音译为阿帕奇)是世界使用排名第一的Web 服务器 软件。它可以运行在几乎所有广泛使用的计算机平台上...

6

四川vps高防空间(高防VPS服务器) 10分钟前

目录:1、哪里的vps便宜好用还高防,主要用于游戏服务器2、VPS、空间哪里的便宜?3、虚拟空间 如何高防抗攻击的吗4、高防云主机跟VPS有什...

7

Remix OS被指违反GPL和Apache许可证 13分钟前

Remix OS项目将移动版的Android操作系统带到了桌面上。但测试者很快注意到这个项目存在违反开源许可证的情况:它的Remix OS USB Tool软件其实是...

8

Ubuntu下安装和使用Zeit具体方法 14分钟前

Zeit是一个开源工具,用于通过crontab和at来调度任务。它提供了一个简单的接口来安排一次性的任务或重复性的任务。Zeit还带有一个闹钟和计...