本博客采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本博客文章必须也遵循 署名-非商业用途-保持一致 的创作共用协议.
简介
NoSQL主要用于Web网站建设, 属于菲关系型数据库, 主要解决:
- 对数据库的高并发要求
- 对海量数据的高效率存储和访问
- 对数据库的高可扩展性和高可用性的需求
作为一个面向文档的数据库, MongoDB
是一个更加通用的NoSQL方案. 可以认为它是关系数据库的一个替代方案, 提供了 高性能, 高可用性, 自动扩展
- 一个记录在MongoDB被称为一个
文档
- 一个
文档
由域(field)和值(value)对组成(可以理解为key-value对) - 值可能又包含其他文档(嵌套概念)
- MongoDB的文档类似与JSON对象
- MongoDB想所有文档存储在
Collections
中(类似与关系数据库中的表概念) - MongoDB支持
二级索引
MongoDB中的文档可以想象成Python中字典数据结构注意掌握索引的应用, 加快大数据时查找速度
安装
#更新brew和brew cask
$ brew update && brew upgrade brew-cask && brew cleanup && brew cask cleanup
#使用brew安装mongodb
$ brew install mongodb
#在根目录下创建用于数据库写存储数据
$ mkdir -p /data/db
#注意查看该目录的权限, 一定要保证是当前用户权限, 而不是root权限
#运行Mongndb
$ mongod
#使用shell操作
$ mongo
基本操作
MongoDB不需要创建表操作
unicorns以及system.indexes。 system.indexes
在每个数据库中都会创建,它包含了数据库中的索引信息。
插入
- 使用
db.collection.insert()
向collection(相当于表名)中插入文档(document) - 返回一个WriteResult对象, 包含操作创建
db .unicorns .insert ( { name : 'Horny' , dob: new Date ( 1992 , 2 , 13 , 7 , 47 ), loves: [ 'carrot' , 'papaya' ], weight: 600 , gender: 'm' , vampires: 63 });
db .unicorns .insert ( { name : 'Aurora' , dob: new Date ( 1991 , 0 , 24 , 13 , 0 ), loves: [ 'carrot' , 'grape' ], weight: 450 , gender: 'f' , vampires: 43 });
db .unicorns .insert ( { name : 'Unicrom' , dob: new Date ( 1973 , 1 , 9 , 22 , 10 ), loves: [ 'energon' , 'redbull' ], weight: 984 , gender: 'm' , vampires: 182 });
db .unicorns .insert ( { name : 'Roooooodles' , dob: new Date ( 1979 , 7 , 18 , 18 , 44 ), loves: [ 'apple' ], weight: 575 , gender: 'm' , vampires: 99 });
db .unicorns .insert ( { name : 'Solnara' , dob: new Date ( 1985 , 6 , 4 , 2 , 1 ), loves:[ 'apple' , 'carrot' , 'chocolate' ], weight: 550 , gender: 'f' , vampires: 80 });
db .unicorns .insert ( { name : 'Ayna' , dob: new Date ( 1998 , 2 , 7 , 8 , 30 ), loves: [ 'strawberry' , 'lemon' ], weight: 733 , gender: 'f' , vampires: 40 });
db .unicorns .insert ( { name : 'Kenny' , dob: new Date ( 1997 , 6 , 1 , 10 , 42 ), loves: [ 'grape' , 'lemon' ], weight: 690 , gender: 'm' , vampires: 39 });
db .unicorns .insert ( { name : 'Raleigh' , dob: new Date ( 2005 , 4 , 3 , 0 , 57 ), loves: [ 'apple' , 'sugar' ], weight: 421 , gender: 'm' , vampires: 2 });
db .unicorns .insert ( { name : 'Leia' , dob: new Date ( 2001 , 9 , 8 , 14 , 53 ), loves: [ 'apple' , 'watermelon' ], weight: 601 , gender: 'f' , vampires: 33 });
db .unicorns .insert ( { name : 'Pilot' , dob: new Date ( 1997 , 2 , 1 , 5 , 3 ), loves: [ 'apple' , 'watermelon' ], weight: 650 , gender: 'm' , vampires: 54 });
db .unicorns .insert ( { name : 'Nimue' , dob: new Date ( 1999 , 11 , 20 , 16 , 15 ), loves: [ 'grape' , 'carrot' ], weight: 540 , gender: 'f' });
db .unicorns .insert ( { name : 'Dunx' , dob: new Date ( 1976 , 6 , 18 , 18 , 18 ), loves: [ 'grape' , 'watermelon' ], weight: 704 , gender: 'm' , vampires: 165 });
可以创建一个变量, 保存多个要插入的文档
var mydocuments = [
{name: 'Leia' , dob: new Date ( 2001 , 9 , 8 , 14 , 53 ), loves: [ 'apple' , 'watermelon' ], weight: 601 , gender: 'f' , vampires: 33 },
{name: 'Dunx' , dob: new Date ( 1976 , 6 , 18 , 18 , 18 ), loves: [ 'grape' , 'watermelon' ], weight: 704 , gender: 'm' , vampires: 165 }
]
#插入到collection
db.unicorns.insert(mydocuments)
查找
查找规则
- 默认情况下, 会返回_id域, 可以使用
_id:0
不映射_id域 - 在
mongo shell
中find默认返回前20个查找到的文档 - 使用
find()
不加任何参数, 等价于find({}), 表示select * from collection
- find({
: })表示使用一个key-value作为选择条件 - and条件, find({
: , : , …}) - or条件, find( $or : [{
: }, { : }, …])
db .users .find ( #user 是 collection (相当于关系数据库中的 from )
{ age : { $gt : 18 } }, #查询条件(相当与 where )
{ name : 1 , address : 1 }#映射域(相当于 select 后指明的列)
) .limit (5) #cursor 修改符
#查找所有体重超过700磅的雄性独角兽的命令
db.unicorns.find({gender: 'm' , weight: { $gt : 700 }})
//或者 (效果并不完全一样,仅用来为了演示不同的方法)
db.unicorns.find({gender: { $ne : 'f' }, weight: { $gte : 701 }})
$lt、$lte、$gt、$gte以及$ne
分别表示小于、小于或等于、大于、大于或等于以及不等于, $exists
操作符用于匹配一个域是否存在, $or操作符并作用于需要进行或操作的数组, 更多查询符可以查看 Query and Projection Operators
db .unicorns .find ( { vampires : {$exists: false }})
# 返回所有或者喜欢苹果,或者喜欢橙子,或者体重小于500磅的雌性独角兽
db .unicorns .find ( { gender : 'f' , $or: [{loves: 'apple' }, { loves : 'orange' }, { weight : {$lt: 500 }}]})
- find的第二个可选参数(
该参数是一个列表
), 用户指明find读取的域
#只返回 name 域(_ id 域默认总是返回)
db .unicorns .find ( null , { name : 1 })
#不返回_ id 域
db .unicorns .find ( null , { name : 1 , _id : 0 })
排序
1表示升序, -1表示降序
#只查看名字和体重, 并按照体重降序排序
db .unicorns .find ( null , { name : 1 , weight : 1 , _id : 0 }) .sort ( { weight : - 1 })
#优先按照名字升序排序再按照吸血降序排序
db .unicorns .find () .sort ( { name : 1 , vampires : - 1 })
计数
- count命令
#返回吸血大于50的个数
db .unicorns .count ( { vampires : {$gt : 50 }})
更新
-
update
根据所给条件找到文档, 然后用新的文档覆盖找到的整个文档
接收参数:
- 查找需要的更新文档的匹配条件
- 更新操作
- 可选的参数
默认情况下, update()更新单个文档, 如果需要更多多个文档, 使用 multi
可选参数
#找到原来 name 所在域, 替换为体重文档
db .unicorns .update ( { name : 'Roooooodles' }, { weight : 590 })
- mongo的
$set
修改符可以实现仅改动某个文档的某个值或几个域
db .unicorns .update ( { name : 'Roooooodles' }, { $ set : {weight : 590 }})
-
$inc
修改符激昂一个域值增加一个正或负的值
db .unicorns .update ( { name : 'Pilot' }, { $ inc : {vampires: - 2 }})
-
$push
修改符增加一个新的值
db .unicorns .update ( { name : 'Aurora' }, { $ push : {love : 'sugar' }})
插新
upsert
意思为如果存在则更新, 否则插入, 使用时将update第三个参数设置为true
#不存在, 插入
db .unicorns .update ( { name : 'liu' }, { $ inc : {hit : 1 }}, true )
#再次执行, 则进行+1操作
db .unicorns .update ( { name : 'liu' }, { $ inc : {hit : 1 }}, true )
#或者设置
db .unicorns .update ( { name : 'liu' }, { $ inc : {hit : 1 }}, { upsert : true })
多重更新
- 将
update
第四个参数设置为true, 表示对所有文档进行修改
db .unicorns .update ( { } , { $ set : {vaccinated : true }}, false , true )
#或者设置 multi
db .unicorns .update ( { } , { $ set : {vaccinated : true }}, { multi : true })
删除
删除collection中所有文档, 更高效的删除所有文档是使用 drop()
db .unicorns.remove({})
#更高效删除drop(), 不需要任何参数
db .unicorns.drop()
删除符合匹配条件的文档
db .unicorns .remove ( { vaccinated : true })
索引
索引的常见组织方式:
- 信息(对象/实例)关联一些特征(
正向索引
) - 每个特征后关联一批信息(对象/实例)(
反向索引又称倒排索引
)
MongoDB支持高效的索引查询, 索引是一个 数据结构
, 它收集collection中文档特定字段的值, MongoDB的查询优化器能够使用这种数据结构快速的对collection的文档进行查询和排序, 索引通过 B-Tree
实现
在MongoDB 3.0.0版本, ensureIndex()创建索引已经过时(不推荐使用), 请使用 createIndex()创建索引
索引类型
-
_id
索引(唯一, 默认创建) - 用户自定义升序/降序的单field索引
- 复合索引(多field), 其中
field出现顺序与索引排序相关
- 文本索引, 支持查找collection中的string内容
- 哈希索引,对field对应的值进行哈希作为索引,(only support equality matches)
索引特点
- MongoDB中索引是大小写敏感的
- 索引保存在system.indexs中, 运行
db.system.indexs.find()
查看
MongoDB官方文档的详细描述
创建索引
基本索引
#当索引不存在时以 name filed 创建单 field 索引
db .unicorns .createIndex ( { name : 1 })
field对应的值表示索引类型, 1表示索引为升序, -1表示索引为降序
唯一索引
如果对要创建唯一索引的field, 存在相同的值(value不唯一), 则不能创建唯一索引
#以 name field 创建唯一索引
db .unicorns .createIndex ( { name : 1 }, { unique : true })
#以 a 和 b field 创建唯一复合索引
db .unicorns .createIndex ( { a : 1 , b : 1 }, { unique : true })
#如果一定要创建对有相同值的键创建唯一索引, 让系统保存第一条记录, 其余删除, 使用 dropDups 参数
db .unicorns .createIndex ( { name : 1 }, { unique : true, dropDups : true })
内嵌文档中的key
MongoDB一个文档中的某个key创建索引
db .unicorns.createIndex({ "address.city" : 1 })
文档索引
db .unicorns.createIndex({ "address" : 1 })
复合索引
#以address中privince, city, postcode, room作为索引
db.unicorns.createIndex({ "address.province" : 1 , "address.city" : 1 , "address.postcode" : 1 , "addresss.room" : 1 })
background索引
默认情况MongoDB在foreground(前景)中创建索引, 防止创建索引时的读写操作(同步阻塞的概念), 背景(background)允许创建索引的同时读写操作, 适用于大批量数据建立索引
#背景创建索引 background 参数为 true
db .unicorns .createIndex ( { name : 1 }, { background : true })
文本索引(important)
可以对field, 值为字符串或字符串数据的field创建文本索引
#对name和subject创建文本索引
db.unicorns.createIndex({name : "text" , subject : "text" })
#设置所有包含字符串的field为索引, 并命名为TextIndex
db.unicorns.createIndex(
{ "$**" : "text" },
{name: "TextIndex" }
)
查看索引
#查看当前collection中所有索引
db.unicorns.getIndexs()
删除索引
#删除 collection 中某个索引
db .unicorns .dropIndex ( { name : 1 })
适用场景和不足
适用场景
- 结构不固定, 有数据的嵌套
- 要求高并发性
- 频繁的数据水平拆分
- 内存大于数据量
不足之处
- 比较占用硬盘空间, 性能受内存影响
- 性能依赖内存, 同时无法指定内存大小, 容易被其他程序占用
- MongoDB不支持事务, 不支持join
- 每个Document限制是最大不超过4MB
参考链接
- NoSQL
- MongoDB Key/value硬盘存储
- Redis Key/value RAM存储
- MemcacheDB Key/value硬盘存储
- The Little MongoDB Book
- Mongo offical Doc
- SQL to MongoDB Mapping Chart