[关闭]
@happyfans 2015-10-27T13:20:24.000000Z 字数 6374 阅读 1927

mongodb入门

mongo


mongo数据模型

文档与集合

文档时mongo的核心概念,本质是是一种BSON(Binary JSON)数据,BSON是一种类JSON的二进制数据,可以在为JSON基础上添加了一些新的数据类型,包括日期、Int32、Int64,常被作为数据存储和网络数据交换的格式,缺点是空间利用率并不理想(存在键名的冗余信息)。BSON由多组键值对组成,具有轻量性、可遍历性和高效性,其中可遍历性是mongo将其作为数据存储的主要原因

mongo和关系型数据库可以按照下图进行理解:
mongo和rdb的对照

mongo文档的注意事项 

  1. 写操作的原子性限制在文档级别
  2. 单个文档的存储大小限制为16MB(防止读取大文档时对内存和网络造成压力)
  3. mongo会尽量保持插入文档时键值对的顺序,但是更新操作可能会改变字段的顺序,因为可能会导致文档内存的重新分配

文档键的命名

  1. _id是系统保留关键字,默认主键,集合中唯一,一旦生成不可更改
  2. 键名不能包含\0或者空字符,因为mongo依靠此判断键的结尾
  3. 键名不能以$开头,不能包含.
  4. 键名区分大小写

集合

把一组相关文档放到一起就组成了集合。我们可以将集合类比成RDB中的表,文档则是一条条的记录。在mongo中集合也是自由的,一个集合中的文档可以是不同的。mongo提供了一些特殊功能的集合:capped collection(固定集合),system.indexessystem.namespaces(这两个用于存储集合的元数据)。集合名字中的.表示子集合。

数据库

多个文档组成集合,多个集合组成数据库。一个mongo instance可以承载多个数据库,每个DB拥有不同的权限,不同的DB也可以分散在DB的各个目录(启动时需要directoryperdb指定)

命名空间

把数据库名添加到集合名前面,中间用点号连接,得到集合的全限定名就是namespace,例如:test_db.testcollection
需要说明的是,.还可以出现在集合名字中,例如:test_db.blog.poststest_db.blog.authors,我们可以将postsauthors看做是blog集合的子集合

mongo数据类型

mongo支持的数据类型非常丰富:
mongo数据类型
如下的命令db.collection.find({name:{$type:2}})将查找name字段为String类型的文档。由于mongoshell默认是javascript shell,所以我们插入的数据是double类型,如果需要插入int类型可以使用NumberInt(x).
ObjectId可以保证在分布式环境下唯一,由24个16进制字符组成,总共需要12字节存储空间:
mongo-object-id

  1. > x = ObjectId()
  2. ObjectId("562f741336aeb42b3fdef2da")
  3. > x.getTimestamp()
  4. ISODate("2015-10-27T12:54:43Z")
  5. > x.valueOf()
  6. 562f741336aeb42b3fdef2da

mongo内嵌文档

文档可以作为键的值,这样的文档叫做内嵌文档。内嵌文档使得数据不用保存成扁平结构的键值对,从而使数据组织方式更加自然

关闭mongoDB

  1. # 切换到admin,执行db.shutdownServer()
  2. use admin
  3. db.shutdownServer()
  4. # 先查看mongo的pid,然后kill此进程
  5. ps -ef | grep mongodb
  6. kill 25414

mongo常用命令

  1. show dbs # 查看数据库
  2. show collections # 查看所有的集合
  3. use test # 切换数据库(需要的时候自己创建)
  4. db.dropDatabase() # 删除当前使用的数据库

向mongo中写入数据

mongo中的collection类似于RDBMS中的表,写入数据的语法:

  1. db.collection_name.insert(BSON)

插入的时候如果没有指定_id字段,则mongo会自动生成一个id,我们也可以自己指定_id,该字段默认创建索引。

我们可以使用js语法插入多条数据

  1. for(var i = 0;i < 10;i++) db.test_collection.insert({x:i})

在mongo中查找数据

查找数据使用find()命令

  1. db.colletion_name.find() # 查询条件为空返回所有文档
  2. db.collection.findOne() # 返回第一条数据

我们可以对find操作产生的文档进行额外的统计

  1. db.test_collection.find().count() # 计数
  2. db.test_collection.find().skip(3) # 跳过前3条数据
  3. db.test_collection.find().limit(5) # 仅返回前5条数据
  4. db.test_collection.find().sort({x:-1}) # 以x字段降序排列,如果指定1则表示升序排列

以上的操作可以连缀进行,例如:

  1. db.test_collection.find().skip(3).limit(4).sort({x:1})

更新mongo数据

更新数据使用update,需要指明查询条件和更新条件,例如:

更新一个文档对象

  1. db.test_collection.update({x:2},{x:'hello'})

注意:与RDBMS不同的是mongo默认更新一条数据,这样设计的初衷是防止不小心更新多条数据。如果需要更新多条数据参见更新多条数据

更新一个文档的部分字段

  1. db.test_collection.insert({x:100,y:200}) # { "x" : 100, "y" : 200 }
  2. db.test_collection.update({x:100},{$set:{y:-1}}) # 仅更新y字段,{ "x" : 100, "y" : -1 }
  3. # 如果使用以下的语法将会完全替代原来的数据
  4. db.test_collection.update({x:100},{y:-1}) # { "y" : -1 }

更新一个文档,如果文档不存在则创建之

只需要指定update的第三个参数为true即可。

  1. db.test_collection.update({x:1111},{x:9999},true) # 数据{ x:1111 }原先并不存在

批量更新文档

实际上更新数据的update语句还有第4个参数表示更新多条数据。

  1. for(var i = 0;i < 3;i++) db.test_collection.insert({x:888}) # 写入3个文档
  2. db.test_collection.update({x:888},{$set:{x:999}},false,true) # 更新3个文档

删除数据

数据的删除使用remove,与查找数据相比,删除数据有以下不同:

  1. db.test_collection.remove({x:999})

清除某个集合中的所有文档(table)

  1. db.test_collection.drop()
  2. show tables # 看不到任何数据

索引

查看索引

  1. db.test_collection.getIndexes() # 查看索引

mongo索引

创建索引

创建索引

索引的分类

  1. { author:"", title:"", article:"" }
  1. # 建立方法
  2. db.arcicles.ensureIndex({key:"text"})
  3. db.arcicles.ensureIndex({key_1:"text",key_2:"text"})
  4. db.arcicles.ensureIndex({"$**":"text"})
  5. # 使用全文索引进行查询
  6. db.arcicles.find({$text:{$search:"coffee"}})
  7. db.arcicles.find({$text:{$search:"aa bb cc"}}) # 包含aa或bb或cc
  8. db.arcicles.find({$text:{$search:"aa bb -cc"}}) # 包含aa或bb 但不包含cc
  9. db.arcicles.find({$text:{$search:"\"aa\" \"bb\" \"cc\""}}) # 同时包含aa、bb、cc的需要将字符串包裹起来

全文检索相似度查询$meta,写在查询条件后面可以返回结果的相似度,与sort一起使用可以达到很好的实用效果。我们可以模拟一个类似于百度的搜索

  1. {score:{$meta:"textScore"}}

全文检索相似度查询

地理位置索引

将一些点的位置存储在mongo中,创建索引后可以按照位置来找到其他点。地理位置索引有2个子分类:

2D索引

查找方式:

2D索引的创建方式

  1. db.collection.ensureIndex({"w":"2d"})

位置的表示方式是经纬度[经度,纬度],取值范围经度[-180,180],纬度[-90,90]

2D索引查询的方式

  1. # 创建2D索引
  2. db.location_collection.ensureIndex({"w":"2d"})
  3. # 插入数据
  4. db.location_collection.insert({w:[1,1]})
  5. db.location_collection.insert({w:[1,2]})
  6. db.location_collection.insert({w:[3,2]})
  7. db.location_collection.insert({w:[90,50]})
  8. # 使用$near查询距离(1,1)最近的点
  9. db.location_collection.find({w:{$near:[1,1]}}) # 返回4条数据
  10. # 使用$maxDistance进行限制
  11. db.location_collection.find({w:{$near:[1,1],$maxDistance:10}}) # 返回前3条数据
  12. # 查询位于[0,0]-[3,3]矩形内的点
  13. db.location_collection.find({w:{$geoWithin:{$box:[[0,0],[3,3]]}}}) # 返回前3条数据
  14. # 查询圆内的点
  15. db.location_collection.find({w:{$geoWithin:{$center:[[0,0],2]}}}) # 1条结果
  16. # 位于多边形内的点
  17. db.location_collection.find({w:{$geoWithin:{$polygon:[[0,0],[1,1],[2,5]]}}}) # 2条

geoNear查询

该查询可以看做是$near查询的进化版,geoNear查询使用runCommand命令

  1. db.runCommand({
  2. geoNear:<collection>,
  3. near:[x,y],
  4. minDistance:(对2D索引无效),
  5. maxDistance:
  6. num:
  7. ...
  8. })

geoNear查询

2Dsphere索引

2Dsphere索引是球面地理位置索引,创建方式:

  1. db.collection.ensureIndex({"w":"2dsphere"})

位置的表示方式不再是经度和纬度,而是一种名为GeoJSON的数据结构,GeoJSON用来描述一个点、一条直线、多边形等形状。格式如下:

  1. {type:"",coordinates:[<coordinates>]}

2Dsphere索引的查询方式和2d索引的查询方式类似,支持$minDistance$maxDistance

索引的mongo性能分析

索引的利弊

评判索引构建情况

  1. mongostat工具
    mongostat是查看mongo运行状态的程序,我们可以使用mongostat --help查看mongo的使用帮助,flushes表名将内存中的数据刷入硬盘(越高则性能越低);faults换页,越高性能越低;ids miss查询没有命中索引的比例;qr|qw读写队列,较高时性能明显下降。ids miss的提高会导致qr的提高导致明显的性能问题。

  2. profile集合
    profile集合是mongo的慢操作日志
    mongo-profile
    当mongo的级别为0的时候不会记录任何操作,2则记录所有的操作。我们的操作就是被记录在system.profile集合中。
    db.system.profile
    profile主要用于测试阶段,生产环境中并不推荐profile

  3. mongo日志
    在mongo的配置文件mongod.conf中可以配置verbose来记录日志的详细程度。

  4. explain分析
    在特定查询的时候可以指定explain()来查看特定查询的情况:
    使用explain查看特定查询的性能

mongo安全

mongo开启权限认证:

mongod.conf中配置auth = true开启权限认证。之后重启mongo,查看mongo日志,搜索auth发现已经有了鉴权启动的标志。

创建用户

mongo2.6之后使用createUser命令创建用户,之前的版本只有简化的addUsercreateUser接收的参数:

  1. {
  2. user:"<name>",
  3. pwd:"<cleartext password>",
  4. customData:{<any information>},
  5. roles:[{role:"<role>",db:"<database>"}]
  6. }

mongo角色

mongo的角色类型有很多,mongo内建的类型有:

我们可以使用createRole命令创建自定义角色。
创建自定义角色

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注