《Node.js 实战》读书笔记(四)

268 阅读4分钟

第五章 存储Node程序中的数据

一、无服务器的数据存储:内存存储和基于文件的存储

1、内存存储

  • 使用场景:存放少量经常使用的数据(如跟踪记录最近一次重启服务器后页面访问次数),服务器和程 序重启后数据就丢了。

2、基于文件的存储 fs

  • 使用场景:保存程序的配置信息,数据的持久化保存,在程序和服务器重启后依然有效。
  • 并发问题:两个用户可能会同时加载相同的文件进行修改。保存一个版本会覆盖另外一个,导致其中某个用户的修改丢失。对于多用户程序而言,数据库管理系统是更合理的选择,因为它们就是为应对并发问题而生的。

二、关系型数据库管理系统 ——MySQL和PostgreSQL

关系数据库管理系统(RDBMS)可以存储复杂的信息,并且查询起来很容易。

1、MySQL

  • 使用步骤

(1)安装MySQL Node模块

npm install mysql

三、NoSQL 数据库—— Redis 和 MongoDB

很多NoSQL数据库把性能放在了第一位,对于实时分析或消息传递而言,NoSQL数据库可能是更好的选择。NoSQL数据库通常也不需要预先定义数据schema,对于那种要把数据存储在层次结构中,但层次结构却会发生变化的程序而言,这很有帮助。

1、Redis

  • 适应场景:处理那些不需要长期访问的简单数据存储,比如短信和游戏中的数据。

  • 特点:

(1)Redis把数据存在RAM中,并在磁盘中记录数据的变化。这样做的缺点是它的存储空间有限,但好处 是数据操作非常快。如果Redis服务器崩溃,RAM中的内容丢了,可以用磁盘中的日志恢复数据。

(2)提供了实用的原语命令集,可以处理几种数据结构。哈希表、链表、键/值对(作为简单的变量使用)、集合(set)

  • 使用步骤

(1)安装node_redis模块

npm install redis

(2)连接Redis服务器

连接到运行在同一主机,默认TCP/IP端口上的Redis服务器。你创建的这个Redis 客户端继承了EventEmitter的行为,当客户端跟Redis服务器通信出现问题时,它会抛出一个 error事件。

var redis = require('redis');
var client = redis.createClient(6379, '127.0.0.1');

client.on('error', function (err) {
  console.log('Error ' + err);
});

(3)操作Redis中的数据

// 存储和获取键/值对
client.set('color', 'red', redis.print);
client.get('color', function(err, value) {
  if (err) throw err;
  console.log('Got: ' + value);
});

2、MongoDB

MongoDB数据库把文档存在集合(collection)中。它们不需要相同的schema,每个文档都可以有不同的schema。 这使得MongoDB比传统的RDBMS更灵活,因为你不用为预先定义schema而操心。

  • 使用步骤

(1)安装MongoDB

npm install mongodb

(2)连接MongoDB

var mongodb = require('mongodb');
var server = new mongodb.Server('127.0.0.1', 27017, {});
var client = new mongodb.Db('mydatabase', server, {w: 1});

(3)访问MongoDB集合

client.open(function(err) {
  if (err) throw err;
  client.collection('test_insert', function(err, collection) {
    if (err) throw err;
	console.log('XXX') // 把 MongoDB 查询代码放在这里
    collection.insert(// 将一个文档插入到集合中,并输出其独有的文档ID
      {
        "title": "I like cake",
        "body": "It is quite good."
      },
      {safe: true},// 安全模式表明数据库操作应该在回调执行之前完成
      function(err, documents) {
        if (err) throw err;
        console.log('Document ID is: ' + documents[0]._id);
      }
    );
  });
});

安全模式:在查询语句中声明{safe: true}表明你想让数据库操作在执行回调之前完成。如果你的回调逻辑对即将完成的数据库操作有任何形式的依赖,这就是你需要的选项。如果你的回调逻辑不依赖于数据库操作,可以用{}取代{safe: true}关闭安全模式

尽管你能用console.log将documents[0]._id显示为字符串,但实际上它不是字符串。MongoDB的文档标识符是二进制JSON(BSON)。BSON是MongoDB用来交换数据的主要数据格式,MongoDB服务器用它代替JSON交换数据。大多数情况下,它更节省空间,解析起来也更快。占用更少空间,扫描更容易意味着数据库交互更快。

(4) 更新MongoDB文档

    var _id = new client.bson_serializer .ObjectID('4e650d344ac74b5a01000001');
    collection.update(
      {_id: _id},
      {$set: {"title": "I ate too much cake"}},
      {safe: true},
      function(err) {
        if (err) throw err;
      }
    );

3、Mongoose Mongoose的模型(模型视图控制器中的说法)提供了一个到MongoDB集合接口

  • 使用步骤

(1)安装Mongoose

npm install mongoose

(2)启动MongoDB服务器

var mongoose = require('mongoose');
var db = mongoose.connect('mongodb://localhost/tasks');

(3)注册schema

var Schema = mongoose.Schema;
var Tasks = new Schema({
  project: String,
  description: String
});
mongoose.model('Task', Tasks);

(4)添加任务

var Task = mongoose.model('Task');
var task = new Task();
task.project = 'Bikeshed';
task.description = 'Paint the bikeshed red.';
task.save(function(err) {
  if (err) throw err;
  console.log('Task saved.');
});

(5) 搜索文档

var Task = mongoose.model('Task');
Task.find({'project': 'Bikeshed'}, function(err, tasks) {
  for (var i = 0; i < tasks.length; i++) {
    console.log('ID:' + tasks[i]._id);
    console.log(tasks[i].description);
  }
});