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 使用点号
使用
.
查找文档中的内嵌信息,处理数组时代码更加简单。比如找到所有办函了特定歌曲的CDdb.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
过滤结果
该操作符可以过滤出文档中数组大小符合条件的结果,比如搜索只含有两首歌曲的CDdb.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 } })
- 删除所有指定值
$pull
db.media.updateOne({"ISBN": "987-1-4842-1183-1"}, {$pull: {Author: "Griffin, Stewie" } })
- 删除数组中多个元素
$pullAll
db.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()