学习MongoDB心得
前言
其实写这个 MongoDB心得 的初衷和我当年整理的 js大脑图 比较一致,而且确实对于我个人而言,每个时间段还是希望要有一些整理性质的东西输出出来,分享给需要的人。
这个系列题目和我自己目前在写的 yc (a fancy node develop platform) 一样,架子都很庞大,但是我还是会坚持写下去,希望感兴趣的同学多多关注。
简介
本文介绍一些基本概念,涉及到文档、集合和数据库,以及一些基本的操作。
那MongoDB是干嘛的呢?其实关键词还是NoSQL
安装
本文只介绍mac上的安装更多可以猛戳:官方文档,本文不做过多描述,只是提醒需要手动地创建一个数据目录,后面会介绍它的作用。
基础的概念
文档
先看一个我们熟悉的js里面的对象:
shell
{"name" : "yaochun" , "company" : "wandoujia" , "group" : "w3cplus" , "job" : "fe"}
其实这也是MongoDB里面的核心概念:文档
就是键值对,但是有一些特有的特性:
一、这个键值对是有序的:
shell
{ "name" : "yaochun" , "company" : "wandoujia" }
{ "company" : "wandoujia" , "name" : "yaochun" }
所以以上两个文档是不一样的。
二、键是字符串,不能还有\0
,.
和 $
有特别的意义,_
开头的是保留的
三、值可以是双引号的字符串,也可以是其他几种数据类型。
四、区分类型和大小写:
shell
{ "name" : "yaochun" , "company" : "wandoujia" , "age" : 50 }
{ "company" : "wandoujia" , "name" : "yaochun" , "age" : "50" }
所以以上两个文档也是不一样的。
五、文档里面的键不能重复,否则视为非法。
集合
集合其实就是一组文档。
集合的命名也有规则:
- 不能是空字符串
- 也不能还有
\0
字符 - 不能以一些系统集合的保留的前缀,比如
system.
这样开头 - 也不能包含$
集合里面有没有数学里面的子集合呢?可以用.
来划分子集合。
数据库
数据库其实是由多个集合组成。数据库之间是相对独立的,存储在不同的文件中。
数据库的命名同样也有规则:
- 不能是空字符串
- 也不能还有
\0
、$
类似这些字符 - 小写
- 最多64字节
因为数据库名其实最终都会变成文件系统的文件,所以命名有一定的约束。
保留的数据库名词:
- admin
- local
- config
数据类型介绍
其实大家发现没有,文档的结构类似我们常用的JSON。那在MongoDB里面的有哪些数据类型呢?
null
shell
{ "freetime" : null }
日期
shell
{ "date" : new Date() }
数组
实例:
shell
{ "keywords" : [ "yaochun" , "wandoujia" , "w3cplus" ] }
内嵌文档
实例:
shell
{ "info" : {"yaochun" , "company" : "wandoujia" , "group" : "w3cplus" } }
其实就是文档包含某个文档
正则
实例:
shell
{ "name" : /yaochun/i }
代码
实例:
shell
{ "code" : function() {/*..*/} }
其他的比较基础的比如:布尔、字符串等就不在这里介绍了。
基础的操作
一般包含:插入、更新、删除和查询
插入
实例:
shell
//welcome to join us: http://www.wandoujia.com/join
db.wandoujia.fe.insert({ "name" : "yourname" })
其实插入从上面的实例直观的看到:
- 也是用insert
- insert方法里面传入的其实就是一个文档
那没有什么主键吗?MongoDB的插入操作默认会给文档加一个 _id
。
删除
实例1:
shell
db.book.mongodb.remove()
这个代表我把book这个集合的子集合mongodb的所有文档都删除掉,但是子集合mongodb本身还在,索引也会保留。
实例2:
shell
db.book.mongodb.remove({ "part" : "primary" })
这里给remove这个操作传递了一个文档,做查询和筛选用的。符合条件的文档才会被删除。
这个代表我把book这个集合的子集合mongodb中所有part为primary的删除掉。
查询
初级教程里面我们只是简单地看看基本的查询方式,在中级里面会全面地去学习一下。
实例1:
shell
//welcome to join us: http://www.wandoujia.com/join
db.wandoujia.jobs.find()
实例2:
shell
//welcome to join us: http://www.wandoujia.com/join
db.wandoujia.jobs.find({ "category", "fe" , "level" : 2 })
从上面的实例中,我们看出,最基本的查询可以用find
而且find里面可以传递参数,比如某个或者某几个文档来指定查询的条件。
多维度的查询
find
前面我们简单介绍了一下find的第一个参数,它其实就是一个文档,用来做筛选条件
实例1:
shell
//welcome to join us: http://www.wandoujia.com/join
db.wandoujia.jobs.find()
实例2:
shell
//welcome to join us: http://www.wandoujia.com/join
db.wandoujia.jobs.find({"category", "fe" , "level" : 2})
那么其实我们日期查询里面都有一些对返回的查询结果需要指定或者过滤掉一些无用的键值,如何处理呢?
实例1 :
shell
db.wandoujia.jobs.find({} , {"category" : 1, "base" : 1})
实例2 :
shell
db.wandoujia.jobs.find({} , {"level" : 0})
上面这段其实我们看到:
- find可以指定第二个参数
- 可以只返回第二个参数文档里面指定的字段,这里对应的值是 1
- 剔除查询结果里面的某个键的化,对应的值设置为 0 就可以了
这样的好处其实很明显啦:
- 减少数据的大小
- 节省传输的数据量
- 客户端也能减少解码文档的时间和内存消耗
查询条件
其实我们日常为了做到精确定位,会指定一些查询条件,比如:
<
<=
>
>=
!=
那在MongoDB里面用什么来表示这些比较操作符呢?
$lt
$lte
$gt
$gte
$ne
我们直接看一个实例:
shell
//比如我们找工作有的人只看2级到3级的
db.wandoujia.jobs.find({"level" , {"$gte" : 2, "$lte" : 3})
这里,我们给find传递了一个内嵌文档,内层的文档的key就是$gte和$lte
实例2:
shell
//比如我们找工作有的人不看帝都的
db.wandoujia.jobs.find({"base" , {"$ne" : "beijing"})
这里,$ne
就代表不等于
所以大致的规则:
$lt
、$lte
、$gt
、$gte
、$ne
都是以$
开头,这也验证了我们前面为什么在命名其他的时候不推荐使用$
$lt
、$lte
、$gt
、$gte
、$ne
这些一般都在内层文档里面。
管理MogoDB
其实大家看了很多之后,一定比较想自己动手,去实践一下这些操作。
启动
一般都是作为网络服务器来运行的,客户端可以连接到这个服务器上。
命令行
shell
./mongod
我这里并没有指定任何参数,其实可以从
shell
./mongod -h
控制台会打出一堆的帮助命令,还是很多的,我这边只是简单提几个:
--dbpath
可以指定数据目录,默认都是/data/db
(根目录下的),每一个mongod实例都需要独立的数据目录。而且当mongod启动的时候,数据里面里面都创建一个mongod.lock的文件,防止其他mongod进程来使用这个数据目录。
感兴趣的化,大家可以自己打开对应的数据目录看看。
--logpath 和 --logappend
可以指定日志输出的路径,而且最好配合logappend,大多数情况下,我们还是希望保留原来的日志,做加法,而不是覆盖。
-f
可以指定某个配置文件来加载命令
那配置文件的书写有没有什么要求呢?
shell
# config by yaochun 2013-08-07 pm 07:10
logpath = mongodb.log
- 一般都是#开头的注释
- 注意大小写
当然里面还有很多其他有用的设置,比如:
- port
- jsonp
- ipv6
- noauth
- rest
- httpinterface
等等,有需求的可以直接去看 -h
里面的说明。
MongoDB客户端
服务器启动后,我们需要一个客户端来操作,那么这个客户端是什么呢?
看图上,我们在命令行输入了以下命令:
shell
./mongo
它就是MongoDB shell,也是一个js shell,可以完成与MongoDB实例的交互
注释:其实如果你只是想体验js shell的化,可以输入:
shell
./mongo --nodb
这样的化,就不会连接数据库。
它默认会自动连接到服务器的test数据库,并把这个数据库连接赋值给全局的db变量
如图:
当然如果你希望有帮助文档来看看里面到底有什么命令,可以输入:
shell
help
如图:
一般常用的:
show dbs
返回当前所有的数据库名称
如图:
show collections
返回当前数据库里面的所有集合(注意:里面包含system.*
这个系统的集合)
use wandoujia
比如我现在默认进去在test这个数据库,我现在要切换到wandoujia这个数据库
如图:
db.fe
这样就能访问上面进入的wandoujia这个数据库的fe集合。
shell执行插入
shell
use wandoujia
db.fe.insert({ "name" : "yourname" })
这样wandoujia这个数据库的fe集合里面就多了一个文档
shell执行查询
shell
db.fe.find()
会返回包含刚才插入的那个文档的集合。
shell执行更新
shell
db.fe.update( { "name" : "yourname" }, { "name" : "yourname", "recommender" : "yaochun" })
update至少接受两个参数,第一个是限定条件对应的文档,第二个是新的文档。
你测试后会发现,其实这个更新就是第二个新文档直接覆盖第一个,当然你可以先定义一个变量,这样update的时候,去修改那个变量,然后传递给update就不需要这样写了。
shell执行删除
shell
db.fe.remove({ "recommender" : "yaochun" })
强大的聚合工具
其实简单地讲:计算一些集合里面文档的个数
count
返回某个集合文档的个数
shell
//比如现在wandoujia一共的员工数目
db.wandoujia.staff.count()
那比如我就像知道fe-team里面的人员个数呢?
shell
//比如现在wandoujia一共的员工数目
db.wandoujia.staff.count({ "category" : "fe" })
待续...
以上内容是我最近使用MongoDB的一些心得,如果有不正确之处,还希望大家多多指点,如果您有相关的使用经验,欢迎在下面的评论中与我们一起分享。
关于小春
专注于前端开发,对ECMA底层有深入探究和兴趣…热衷新技术深入调研学习,涉足移动前端许久,爱好分享交流…个人博客focus-fe。欢迎随时关注我:新浪微博
如需转载,烦请注明出处:http://www.w3cplus.com/blogs/spring/mongo-db.html