目标

无明确目标

知识点

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

课程内容

mongodb

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

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

mongodb 的官网是这样介绍自己的:

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

开源、文档型、nosql。

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

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

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

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

假设有一个 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

Mongodb 与 Mongoose 的使用的更多相关文章

  1. Practical Node.js (2018版) 第5章:数据库 使用MongoDB和Mongoose,或者node.js的native驱动。

    Persistence with MongoDB and Mongoose https://github.com/azat-co/practicalnode/blob/master/chapter5/ ...

  2. MongoDB 和 Mongoose 04

    一.安装 1. 相关 https://www.mongodb.org/dl/win32/ MongoDB的版本偶数版本为稳定版,奇数版本为开发版 MongoDB对于32位系统支持不佳,所以3.2版本以 ...

  3. 【重学Node.js 第3篇】mongodb以及mongoose的使用

    mongodb以及mongoose的使用 本篇为这个系列的第三篇,想看更多可以直接去github的项目:https://github.com/hellozhangran/happy-egg-serve ...

  4. 前端知识点回顾——mongodb和mongoose模块

    mongodb和mongoose模块 数据库 数据库有关系型数据库(MySQL)和非关系型数据库(mongodb),两者的语法和数据存储形式不一样. mySQL 关系型数据库 类似于表格的形式,每一条 ...

  5. mongodb用mongoose取到的对象不能增加属性

    先定义了一个article的schema var mongoose = require('mongoose'); var Schema = mongoose.Schema; exports.schem ...

  6. 前端笔记之NodeJS(四)MongoDB数据库&Mongoose&自制接口&MVC架构思想|实战

    一.MongoDB数据库 1.1 NoSQL简介 随着互联网web2.0网站的兴起,传统的SQL数据库(关系数据库)在应付web2.0网站,特别是超大规模和高并发的SNS(social network ...

  7. MongoDB及Mongoose的记录

    MongoDB是一种NoSQL的文档型数据库,其存储的文档类型都是JSON对象. 在node.js中由于代码都是异步执行,且nosql也没有“事物”这一定义,所以日常使用中很难保证数据库操作的原子性. ...

  8. mongoDB与mongoose

    mongodb是一个基于分布式文件存储的文档型数据库 MongoDB 是一个介于关系数据库和非关系数据库之间的产品 MongoDB 最大的特点是他支持的查询语言非常强大,而且还支持对数据建立索引 官方 ...

  9. [转] mongoDB与mongoose

    mongoDB简介 mongoDB与一些关系型数据库相比,它更显得轻巧.灵活,非常适合在数据规模很大.事务性不强的场合下使用.同时它也是一个对象数据库,没有表.行等概念,也没有固定的模式和结构,所有的 ...

  10. mongodb用mongoose查库的对象,不能增加属性

    node + koa2 + mongodb 写了一个给前端的接口 如果不是写这个接口,这辈子都发现不了mongodb里这个大坑 mongoose 是个ODM(Object Document Mappe ...

随机推荐

  1. 以上帝模式管理Windows系统

    上帝模式,,即"God Mode",或称为"完全控制面板".是Windows Vista/7系统中隐藏的一个简单的文件夹窗口,但包含了几乎所有Windows系统 ...

  2. Untracked Files Prevent Checkout move or commit them before checkout

    点开View Files... 查看里面的文件名称,在项目的.idea文件夹中删掉ViewFiles显示的文件夹名称就好

  3. Effective C++:条款26:尽可能延后变量定义式的出现时间

    (一) 那么当程序的控制流到达这个变量定义时.变承受构造成本:当变量离开作用域时.便承受析构成本. string encryptPassword(const std::string& pass ...

  4. ASP.NET之旅--深入浅出解读IIS架构

    在学习Asp.net时,发现大多数作者都是站在一个比较高的层次上讲解Asp.Net. 他们耐心. 细致地告诉你如何一步步拖放控件. 设置控件属性.编写 CodeBehind代码,以实现某个特定的功能. ...

  5. Java从零开始学二十四(集合工具类Collections)

    一.Collections简介 在集合的应用开发中,集合的若干接口和若干个子类是最最常使用的,但是在JDK中提供了一种集合操作的工具类 —— Collections,可以直接通过此类方便的操作集合 二 ...

  6. 算法笔记_189:历届试题 横向打印二叉树(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 二叉树可以用于排序.其原理很简单:对于一个排序二叉树添加新节点时,先与根节点比较,若小则交给左子树继续处理,否则交给右子树. 当遇到空子树 ...

  7. 如何固定OpenERP顶的主菜单,方便滚动至第二屏以及多屏时,快速切换主菜单

    如何固定OpenERP顶的主菜单,方便滚动至第二屏以及多屏时,快速切换主菜单 作者:广州-步科,来自OpenERP应用群() 将“addons\web\static\src\css”目录下的“base ...

  8. 在云主机或vps上用bzr拉OpenERP7.0代码

    前面的文章讲过了用bzr来参与OpenERP开发的过程,其中很重要的一步就是创建本地分支.我在阿里云上建server和web的分支都没有问题,就是addons分支搞了30几次都在中途被kill了. 今 ...

  9. 【Oracle】将表名与字段名连接成一行数据展示,字段名使用顿号的分隔

    select '<'||a.comments||'>:'||replace(wmsys.wm_concat(b.comments),',','.')||'.' as pjzf from u ...

  10. 通过jdbc使用PreparedStatement,提升性能,防止sql注入

    为什么要使用PreparedStatement? 一.通过PreparedStatement提升性能 Statement主要用于执行静态SQL语句,即内容固定不变的SQL语句.Statement每执行 ...