Mongodb 与 Mongoose 的使用

目标

无明确目标html

知识点

  1. 了解 mongodb (http://www.mongodb.org/ )
  2. 学习 mongoose 的使用 (http://mongoosejs.com/ )

课程内容

mongodb

mongodb 这个名词相信你们不会陌生吧。有段时间 nosql 的概念炒得特别火,其中 hbase redis mongodb couchdb 之类的名词都相继进入了大众的视野。node

hbase 和 redis 和 mongodb 和 couchdb 虽然都属于 nosql 的大范畴。但它们关注的领域是不同的。hbase 是存海量数据的,redis 用来作缓存,而 mongodb 和 couchdb 则试图取代一些使用 mysql 的场景。mysql

mongodb 的官网是这样介绍本身的:git

MongoDB (from "humongous") is an open-source document database, and the leading NoSQL database. Written in C++github

开源、文档型、nosql。web

其中文档型是个重要的概念须要理解。redis

在 sql 中,咱们的数据层级是:数据库(db) -> 表(table) -> 记录(record)-> 字段;在 mongodb 中,数据的层级是:数据库 -> collection -> document -> 字段。这四个概念能够对应得上。sql

文档型数据这个名字中,“文档”两个字很容易误解。其实这个文档就是 bson 的意思。bson 是 json 的超集,好比 json 中无法储存二进制类型,而 bson 拓展了类型,提供了二进制支持。mongodb 中存储的一条条记录均可以用 bson 来表示。因此你也能够认为,mongodb 是个存 bson 数据的数据库,或是存哈希数据的数据库。mongodb

mongodb 相对于它的竞争对手们来讲——好比 couchdb,它的一大优点就是尽量提供与 sql 对应的概念。以前说了,sql 中的记录对应 mongodb 中的 document,记录这东西是一维的,而 document 能够嵌套不少层。在某些场景下,好比存储一个文章的 tags,mongodb 中的字段能够轻松存储数组类型,而 sql 中就须要设计个一对多的表关系出来。shell

假设有一个 blog 应用,其中有张 Post 表,表中有用户发表的一些博客内容(post)。

这些 post 文档的样子大概会是这样:

var post = {
  title: '呵呵的一天',
  author: 'alsotang',
  content: '今天网速不好',
  tags: ['呵呵', '网速', '差'],
};

mongodb 中有个最亮眼的特性,就是 Auto-Sharding,sharding 的意思能够理解成咱们 scale sql 时的分表。

在 mongodb 中,表与表之间是没有联系的,不像 sql 中同样,能够设定外键,能够进行表链接。mongodb 中,也没法支持事务。

因此这样的表,无债一身轻。能够很轻易地 scale 至多个实例(假设实例都有不一样的物理位置)上。在 mongodb 中,实时的那些查询,也就只能进行条件查询:某某大于一个值或某某等于一个值。而 sql 中,若是一张表的数据存在了多个实例上的话,当与其余表 join 时候,表之间的运来运去会是个很慢的过程,具体我也不太懂。

反正使用 mongodb 时,必定要思考的两点就是:表 join 到底要不要,事务支持到底要不要。

mongodb 中的索引特性跟 sql 中差很少,只是它对于嵌套的数据类型也提供了支持。在创建复合索引时,mongodb 能够指定不一样字段的排序,好比两个字段 is_top(置顶) 和 create_time(建立时间) 要创建复合索引,咱们能够指定 is_top 按正序排,create_time 按逆序排。mysql 说是有计划支持这个特性,不过目前也没什么消息。不过这点不重要。

mongodb 中,collection 是 schema-less 的。在 sql 中,咱们须要用建表语句来代表数据应该具备的形式,而 mongodb 中,能够在同一张里存各类各样不一样的形式的数据。同一个 collection 中,能够有些 document 具备 100 个字段,而另外一些,则只具备 5 个字段。若是你分不清这个特性的使用场景,那么请像使用 sql 同样的,尽量保证一个 collection 中数据格式是统一的。这个 schema-less 的特性,有个比较典型的场景是用来存储日志类型的数据,能够搜搜看这方面的典型场景。

mongodb 和 mysql 要我选的话,可有可无的应用我会选择 mongodb,就当个简单的存 json 数据的数据库来用;若是是线上应用,确定仍是会选择 mysql。毕竟 sql 比较成熟,并且各类经常使用场景的最佳实践都有先例了。

我所在的阿里巴巴数据平台,有各类各样的大数据系统。有些作离线计算,一算就是几个小时,算出来的结果被缓存起来,查询时候就能够实时获得结果,只是数据一致性上,不可避免会有 delay;有些作实时运算,能够在 1s 内从几千万条数据中算出一个复杂条件的结果。但它们都提供了 sql 的接口,也就是说,不管底层他们是如何让几百台机器 mapreduce,都让你能够用已有的 sql 知识进行查询。因此仍是选择 sql 省事啊。

这里还有个很好玩的网站:http://www.mongodb-is-web-scale.com/

顺便说说 mongodb 与 redis 的不一样。mongodb 是用来存非临时数据的,能够认为是存在硬盘上,而 redis 的数据能够认为都在内存中,存储临时数据,丢了也无所谓。对于稍微复杂的查询,redis 支持的查询方式太少太少了,几乎能够认为是 key-value 的。听说 instagram 的数据就所有存在 redis 中,用了好几个几十 G 内存的 aws ec2 机器在存。redis 也是支持把数据写入硬盘的,aof 貌似都过期了,很久没关注了。

mongodb 与 hbase 的区别。若是说你已经在考虑使用 hbase 了的话,应该也不用我介绍它们的区别了吧..

主题所限,就不展开讲了。这之间的选择和权衡,提及来真的是个很大的话题。

我对这方面的话题很感兴趣,若是要讨论这方面话题的话,能够去 https://cnodejs.org/ 发个帖,详细描述一下场景而后 at 我(@alsotang)。

mongodb 的官网中有一些特性介绍:

其中标有箭头的是基本概念,圆圈的是进阶概念,画叉的没必要了解。

安装 mongodb

课程到这,一直忘记说 mongodb 的安装了。

ubuntu: http://docs.mongodb.org/manual/tutorial/install-mongodb-on-ubuntu/

mac: $ brew install mongodb

装好之后,在命令行 $ mongod,而后另外开个 shell 窗口,输入 $ mongo 就能使用了。

mongoose

mongoose 是个 odm。odm 的概念对应 sql 中的 orm。也就是 ruby on rails 中的 activerecord 那一层。orm 全称是 Object-Relational Mapping,对象关系映射;而 odm 是 Object-Document Mapping,对象文档映射。

它的做用就是,在程序代码中,定义一下数据库中的数据格式,而后取数据时经过它们,能够把数据库中的 document 映射成程序中的一个对象,这个对象有 .save .update 等一系列方法,和 .title .author 等一系列属性。在调用这些方法时,odm 会根据你调用时所用的条件,自动转换成相应的 mongodb shell 语句帮你发送出去。天然地,在程序中链式调用一个个的方法要比手写数据库操做语句具备更大的灵活性和便利性。

mongoose 的官网给出了相似这样一个示例,我改造了一下:

// 首先引入 mongoose 这个模块
var mongoose = require('mongoose');
// 而后链接对应的数据库:mongodb://localhost/test
// 其中,前面那个 mongodb 是 protocol scheme 的名称;localhost 是 mongod 所在的地址;
// 端口号省略则默认链接 27017;test 是数据库的名称
// mongodb 中不须要创建数据库,当你须要链接的数据库不存在时,会自动建立一个出来。
// 关于 mongodb 的安全性,mongodb 我印象中安全机制很残废,用户名密码那套都作得很差,更
// 别提细致的用户权限控制了。不过不用担忧,mongodb 的默认配置只接受来自本机的请求,内网都连不上。
// 当须要在内网中为其余机器提供 mongodb 服务时,或许能够去看看 iptables 相关的东西。
mongoose.connect('mongodb://localhost/test');

// 上面说了,我推荐在同一个 collection 中使用固定的数据形式。
// 在这里,咱们建立了一个名为 Cat 的 model,它在数据库中的名字根据传给 mongoose.model 的第一个参数决定,mongoose 会将名词变为复数,在这里,collection 的名字会是 `cats`。
// 这个 model 的定义是,有一个 String 类型的 name,String 数组类型的 friends,Number 类型的 age。
// mongodb 中大多数的数据类型均可以用 js 的原生类型来表示。至于说 String 的长度是多少,Number 的精度是多少。String 的最大限度是 16MB,Number 的整型是 64-bit,浮点数的话,js 中 `0.1 + 0.2` 的结果都是乱来的。。就不期望什么了。。
// 这里能够看到各类示例:http://mongoosejs.com/docs/schematypes.html
var Cat = mongoose.model('Cat', {
  name: String,
  friends: [String],
  age: Number,
});

// new 一个新对象,名叫 kitty
// 接着为 kitty 的属性们赋值
var kitty = new Cat({ name: 'Zildjian', friends: ['tom', 'jerry']});
kitty.age = 3;

// 调用 .save 方法后,mongoose 会去你的 mongodb 中的 test 数据库里,存入一条记录。
kitty.save(function (err) {
  if (err) // ...
  console.log('meow');
});

咱们能够验证一下

$ mongo
MongoDB shell version: 2.6.4
connecting to: test
> show dbs
> use test
> show collections
> db.cats.find()

会发现里面就有一条记录了。

设计个简单博客程序

若是要写个博客程序练手。数据库能够这样设计

var Post = mongoose.model('Post', {
  title: String,
  content: String,
  author: String,
  create_at: Date,
});

评论就不要本身作了,接入多说:http://duoshuo.com/

编辑器就纯文本好了,用 markdown 写。

用户系统也不作,硬编码几个管理员帐号在配置文件中,而后用 http basic auth:https://github.com/jshttp/basic-auth 来作验证。

示例程序

Nodeclub 是使用 Node.js 和 MongoDB 开发的社区系统

https://github.com/cnodejs/nodeclub

相关文章
相关标签/搜索