1.介绍和安装
1.1 介绍
MongoDB是一个基于分布式文件存储的数据库,是一个介于关系数据库和非关系数据库之间的产品。Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言
1.2 安装
本以为用了Ubuntu就可以不用担心版本问题,结果32bit还是个越不过的坎,当初就是因为mongodb对win7 32bit支持不够友好,所以选择使用Ubuntu,结果我还是太天真,mongodb同样不在支持32bit 的Ubuntu,在官网上已经下载不到32bit的mongodb(哭瞎),于是一顿google加stack overflow,最终还是安装好了
- 下载mongodb
- 将下载的压缩包复制到自己的目录下,解压 tar zxvf mongodb-linux-i686-3.2.13.tgz
- 为了方便,重命名为简短一点的名字mv mongodb-linux-i686-3.2.13.tgz mongodb
- 余下步骤跟win设置差不多,就是最后设置数据库存储路径的时候需要添加额外的参数, 创建目录mkdir db
- 路径 cd ./bin
- ./mongod --dbpath=../db --storageEngine=mmapv1区别就在于最后一行参数
- 开启mongodb ./mongo
2.基本用法
2.1 浏览数据库(这里以数据库library为例)
- 切换到已有数据库或者创建新的数据库 use library
- 查看可用数据库 show dbs或show databases
- 查看可用集合 show collections
- 查看当前使用数据库 db
- 使用集合 db.media(media为集合名)
2.2 集合中插入数据
mongodb使用的是BSON(JSON的二进制)格式存储数据
- 可以先定义数据,然后在调用insertOne函数插入数据库中,media为集合名,不存在的时候会自动创建 - doc = ({"Type": "Book",- … “Title”: “Definitive Guide to MongoDB”, 
 … “ISBN”: “987-1-4842-1183-0”,
 … “Publisher”: “Apress”,
 … “Author”: [“Hows, David”,”Plugge Eelco”,”Membrey, Peter”] })
 db.media.insertOne(doc)
 `
- 直接使用后insertOne方法插入 - db.media.insertOne({ "Type": "DVD", ... "Artist": "Nirvana", ... "Title": "Nevermind", ... "Tracklist": [ ... { ... "Track": "1", ... "Title": "Smells Like Teen Spirit", ... "Length": "5:02", ... }, ... { ... "Track": "2", ... "Title": "In Bloom", ... "Length": "4:15", ... } ... ] ... })- 2.3 查询数据- 使用find函数 
- 查询出集合总所有数据 - db.media.find()
- 查询特定类型的数据 db.media.find({ Artist: "Nirvana" })
- 查询特定类型的数据,但指定显示的信息,在指定的显示信息后面加上参数1 - db.media.find({ Artist: "Nirvana"}, {Title: 1} ),还可以使用参数0来取反,就是除它以外的所有信息- 2.3.1 使用点号- 使用 - .查找文档中的内嵌信息,处理数组时代码更加简单。比如找到所有办函了特定歌曲的CD- db.media.find({"Tracklist.Title": "In Bloom"})- 还可以直接写数组中的项,每一项必须精确匹配。比如查询作者的图书列表,(示例中的作者是以数组的形式存在)。 - db.media.find({"Author":"Membrey, Peter"})- 下面这条语句没有精确匹配,就就查不到任何内容 - db.media.find({"Tracklist": {"Track": "1"}})- 2.3.2 使用函数- sort,- limit和- skip
- sort()可以对查询结果进行排序,使用参数1或-1将结果按照升序或降序排列,不指定参数的或默认为1,即升序- db.media.find().sort({Title: 1})
- limit()限制返回结果的最大数目,参数为数值,默认或者0则返回所有数据。下面表示只返回集合中的前10个文档- db.media.find().limit(10) 
- skip()忽略文档中前n个文档.下面表示忽略文档前20个- db.media.find().skip(20) 
- 可以连用这些函数,实现分页功能 - db.media.find({ Title: -1 }).limit(10).skip(20)- 2.3.3 获取单个文档- findOne()与- limit(1)得到的结果一致,如果获取一个的时候推荐使用- findOne()- db.media.findOne() - 2.3.4 使用聚集命令- Mongodb包含三个基本的聚集函数 - count(),- distinct(),- group()
- count()返回文档数目- 显示集合包含多少个文档 db.media.count()
- 结合操作符使用 db.media.find({ Publisher: "Apress", Type: "Book" }).count()
 
- 显示集合包含多少个文档 
- distinct()获取唯一值- 上面示例查询了指定出版商图书信息的文档数目,但是如果集合总有多本书(实体书和电子书)含有相同标题,实质上他们为同一本书,就可以使用 - distinct()函数获取唯一值- 插入一本书,只修改ISBN号,其他信息相同 - db.media.insertOne({"Type": "Book","Title": "Definitive Guide to MongoDB","ISBN": "987-1-4842-1183-1","Publisher": "Apress","Author": ["Hows, David","Plugge Eelco","Membrey, Peter"]})- 这时数据库中含有两本标题一样的书了 - db.media.distinct("Title")- 输出,另一个结果显示为 - Nevermind- [ "Definitive Guide to MongoDB", "Nevermind" ] - 如果查询ISBN,则会返回两条数据 - db.media.distinct("ISBN")- 输出 - [ "987-1-4842-1183-0", "987-1-4842-1183-1" ] - 可以接受嵌套键 - db.media.distinct("Tracklist.Title")- 输出 - [ "In Bloom", "Smells Like Teen Spirit" ] 
- group()将结果分组- 接受3个参数 - key,- initial,- reduce- `* `key`指定希望使用哪个键对结果进行分组 * `initial` 为每个以分组的结果提供基数。如果希望返回指定的数字,这个参数就应默认为0 * `reduce` 把所有类似的条目分组在一起 ` - 比如,希望获取集合中任何类型的所有唯一标题列表,另外,只要发现任何相同的元素,就基于标题将他么添加到同一组 - db.media.group( { key: {Title: true}, initial: {Total: 0}, reduce: function(items, prev) { prev.Total += 1 } } )- items,- prev参数分别表示正在遍历的当前文档和聚集基数对象,最后结果为- [ { "Title" : "Nevermind", "Total" : 1 }, { "Title" : "Definitive Guide to MongoDB", "Total" : 1 } ]- 2.3.5 使用条件操作符- MongoDB支持大量的条件操作符用于更好的过滤结果。增减一些文档 - db.media.insertOne({"Type": "DVD", "Title": "Matrix, The", "Released": 1999, "Cast": ["Keanu Reeves", "Carrie-Anne Moss", "Laurence Fishburne", "Hugo Weaving", "Gloria Foster", "Joe Pantoliano"]}) db.media.insertOne({"Type": "DVD", "Title": "Blade Runner", "Released": 1982}) db.media.insertOne({"Type": "DVD", "Title": "Toy Story 3", "Released": 2010})
- 执行大于或者小于比较 - $gt,- $lt,- $gte,- $lte- $gt大于,指定文档中的某个整数必须大于指定的值- db.media.find({ Released: {$gt: 2000} }, { "Cast": 0 })
- $gte大于等于- db.media.find({ Released: {$gte: 1999} }, { "Cast": 0 })
- $lt,- $lte分别表示小于和小于等于,用法更上面类似
- 可以结合设置一个范围db.media.find({ Released: {$gte: 1999, $lt: 2010} }, { "Cast": 0 })
 
- 获取除特定文档之外的所有文档$ne
 返回作者不是Plugge Eelco的所有图书db.media.find({ Type: "Book", Author: {$ne: "Plugge Eelco"}})
- 指定一个匹配的数组($in, 相反不在数组中的值$nin,用法一致)
 返回发行年份为数组里面的文档信息db.media.find({Released: {$in: [1999,2008,2009]}}, {"Cast": 0})
- 匹配文档中所有属性( - $all)
 工作方式与- $in类似,区别在与- $all要求所有属性都匹配,- $in匹配一个就行- db.media.find({Released: {$in: [1999, 2000]}}, {"Cast": 0})- 输出 - { "_id" : ObjectId("5922bb479a45340aa9383932"), "Type" : "DVD", "Title" : "Matrix, The", "Released" : 1999 }- 而 - db.media.find({Released: {$all: [1999, 2000]}}, {"Cast": 0})- 不会返回任何东西,文档中没有发行年份为2000的,所以不能完全匹配,则没有结果 
- 文档中搜索多个表达式 - 在单个查询中可以使用 - $or操作符搜索多个表达式,将返回满足其中任何一个条件的文档。与- $in不同,- $or可以同时指定键和值,而不只是指定值- db.media.find({$or: [{ "Title": "Toy Story 3"}, {"ISBN": "978-1-4842-1183-0"}]})- 还可以结合另一个查询参数使用 - db.media.find({"Type": "DVD", $or: [{ "Title": "Toy Story 3"}, {"ISBN": "978-1-4842-1183-0"}]})- 先满足第一个条件,在执行第二个 
- 使用 - $slice获取文档
 该方法可以把数组字段限制为匹配结果的一个数组子集。接受两个参数,第一个参数表示将要返回数据项的总数,第二个为可选参数,如果使用了第二个参数,那么第一个参数将用于定义偏移,第二个参数用于定义限制- 返回Cast列表中前3项 db.media.find({"Title": "Matrix, The"}, {"Cast": {$slice: 3}})
- 可以通过负数获取后3项 db.media.find({"Title": "Matrix, The"}, {"Cast": {$slice: -3}})
- 忽略强两项,并限制返回从某个点开始的3个数据db.media.find({"Title": "Matrix, The"}, {"Cast": {$slice: [2,3] }})
- 忽略最后5项数据,并将结果输出限制4条 db.media.find({"Title": "Matrix, The"}, {"Cast": {$slice: [-5,4] }})
 
- 返回Cast列表中前3项 
- 搜索奇数/偶数$mod
 通过$mod操作符可以搜索由奇数或者偶数组成的特定数据,该操作将把目标值除以2,检查运算余数为0还是为1,余数为0则为偶数,余数为1则为基数db.media.find({ Released: { $mod: [2, 0] }}, {“Cast”: 0})
 奇数
 db.media.find({ Released: { $mod: [2, 1] }}, {“Cast”: 0})注意:只能处理整数,不能处理包含数组的字符串,比如{Released: “2010”} 
- $size过滤结果
 该操作符可以过滤出文档中数组大小符合条件的结果,比如搜索只含有两首歌曲的CD- db.media.find({ Tracklist: {$size:2} })
- 返回含有特定字段的对象
 $exists将在特定字段存在或不存在的情况下,返回该对象,比如返回集合中含有键Author的所有文档db.media.find({Author: {$exists: true} })
 当$exists为false的时候,则返回所有不含Author的文档
- 匹配完整数组 - $elemMatch
 如果集合中有多个文档,其中一些文档包含一些相同的信息,使用- $elemMatch可以进行数组完整匹配。
 新增一条数据,和之前那条- Nirvana的CD包含相同的曲目”Smells Like Teen Spirit”,只不过现在”Smells Like Teen Spirit”为曲目”5”- db.media.insertOne({ "Type": "CD","Artist": "Nirvana","Title": "Nirvana","Tracklist": [{"Track": "1","Title": "You Know You're Right","Length": "3:38",},{ "Track": "5","Title": "Smells Like Teen Spirit", "Length": "5:02", }] })比如查询包含”Smells Like Teen Spirit”的CD,并且曲目为1 使用下面语句,两条结果都会被查询出来- db.media.find({ "Tracklist.Title": "Smells Like Teen Spirit", "Tracklist.Track": "1" })使用`$elemMatch`完整匹配- db.media.find({ Tracklist: { "$elemMatch": { Title: "Smells Like Teen Spirit", Track: "1"} } })
- 指定额外的查询表达式 - 除了目前结构化查询语法,还可以使用JavaScript指定的额外的查询表达式 - 比如,希望查找集合中发布年份早于1995年的DVD,下面这些都可以 - db.media.find({Type: "DVD", "Released": {$lt: 1995}})
 - db.media.find({Type: "DVD", $where: "this.Released < 1995"})
 - db.media.find("this.Released < 1995")
 - f = function() {return this.Released < 1995}
 - db.media.find(f)
2.3.6 使用正则表达式
`db.media.find({Title: /^Matrix*/i})` 待深入研究
2.4 更新数据
2.4.1 使用update()更新
可以接受三个参数criteria,objNew, options
- criteria可以用于指定一个查询
- objNew指定更新信息,也可以使用操作符来完成
- options用于指定更新文档时的选项,可选值为- upsert,- multi。- upsert表示如果数据存在就更新,不存在就创建。- multi可以指定是否应该更新所有匹配的文档,或者只更新第一个文档(默认)- db.media.updateOne({"Title" : "Matrix, The"}, {"Type" : "DVD", "Title" : "Matrix, The", "Released" : 1999, "Genre": "Action"}, {upsert: true})- 使用上条语句,任何忽略的字段都将被移除(该文档基本被重写) - 如果有多个文件符合条件,并且都需要修改,使用 - $updateMany和- $set修饰符- db.media.updateMany({"Title" : "Matrix, The"}, {$set: {"Type" : "DVD", "Title" : "Matrix, The", "Released" : 1999, "Genre": "Action" }}, {upsert: true})
2.4.2 使用save()命令实现upsert
可添加id值,手动或者自动添加该值,不指定的话,就会认为它是一个插入操作,并将文档添加到集合中
db.media.save({"Title" : "Matrix, The"}, {"Type" : "DVD", "Title" : "Matrix, The", "Released" : 1999, "Genre": "Action"})
2.4.3 自动更新信息
- 使用 - $inc增加值
 该操作符可以为指定的键执行(原子)更新操作,如果字段存在,就将该值增加给定的增量。如果不存在,就创建。
 添加一个新的文档- db.media.insertOne({"Type": "Manga", "Title": "One Piece", "Volumes": 612, "Read": 520})- 假设已经阅读到One Piece漫画的4卷内容,就希望更新文档中已读册数的目录 - db.media.updateOne({"Title": "One Piece"}, {$inc: {"Read": 4}})
- 设置字段值 - $set- 通过该操作符将某个字段设置成特定值。下面语句将 - Genre字段的值设置成- Sci-Fi- db.media.updateOne({"Title": "Matrix, The"}, {$set: {Genre: "Sci-Fi"}})
- 删除指定字段 - $unset- db.media.updateOne({"Title": "Matrix, The"}, {$unset: {Genre: 1}})
2.4.4 在指定字段中添加某个值$push
使用它可以在指定字段中添加某个字段。如果该该字段是数组,那么该值将被添加到数组,如果该字段不存在,那么该字段的值将被设置成为数组。如果该字段存在,但不是数组,则报错。
<pre>db.media.updateOne({"ISBN": "987-1-4842-1183-1"}, {$push: {Author: "Griffin, Stewie"}})
</pre>
2.4.5 指定数组中的多个值$each
使用$push操作符可以将值添加到指定数值中,如果希望在给定数组中添加几个不同的值,可以使用$each
<pre>db.media.updateOne({"ISBN": "987-1-4842-1183-0"}, {$push: {Author: { $each: ["Griffin, Stewie", "Griffin, Brian"] } } })</pre>
2.4.6 从数组中删除元素$pop,$pull,pullAll
- $pop可从数组中删除单个元素,允许删除数组中第1个或最后一个,对应参数分别为- 1和- -1- db.media.updateOne({"ISBN": "987-1-4842-1183-1"}, {$pop: {Author: 1 } })
- 删除所有指定值$pulldb.media.updateOne({"ISBN": "987-1-4842-1183-1"}, {$pull: {Author: "Griffin, Stewie" } })
- 删除数组中多个元素$pullAlldb.media.updateOne({"ISBN": "987-1-4842-1183-1"}, {$pullAll: {Author: ["Griffin, Stewie", "Griffin, Brian"] } })
2.4.7 以原子方式修改和返回文档findAndModify
接受三个主要操作符
- <query>用于指定目标文档
- <sort>用于对多个匹配文档进行排序
- <operations>用于希望执行的操作- 比如找到搜索的目标文档并在找到之后删除 - db.media.findAndModify({"Title": "One Piece", sort: {"Title": -1}, remove: true})- 修改,并会返回更新之前的文档 - db.media.updateOne({query: {"ISBN": "987-1-4842-1183-1"}, sort: {"Title": -1}, update: {$set: {"Title": "Different Title"}}})- 想要返回更新之后的文档,需要增加 - new操作符- db.media.updateOne({query: {"ISBN": "987-1-4842-1183-1"}, sort: {"Title": -1}, update: {$set: {"Title": "Different Title"}}, new: true})
2.5 删除数据
- 删除一个文档 db.media.deleteOne({"Title": "Different Title"})
- 删除多个 db.media.deleteMany({})
- 删除整个集合 db.media.drop()
- 删除数据库 db.dropDatabase()