NodeJS 与 MongoDB 的邂逅

虽然 NodeJS 的模块和开发资源相当多,但相关文件却非常不足或是不完整,多半文献都只着重于基础的使用和片断的说明,如果不去看源代码,使用 NodeJS 来完成实用的网站,会有很大的困难度。对于已经有过 Web 开发经验的人,转换使用 NodeJS 不免也需要花一番功夫,过去经验中许多的常用的功能,都仍要一一花大量时间尝试才得以解决。而这样的情况,对于开发者来说相当的糟,也是很多人重新再评估是否使用 NodeJS 的重点因素之一。有道是”一人得道,鸡犬升天”,因此笔者未来将尝试将自己的实际经验,写成一篇篇重点功能实现的文章和随 Copy 即用的范例,减少其他人浪费同样的时间再摸索。

开发一个 Web 应用程序,最重要的莫过于数据库的使用,过去 PHP 有 MySQL 当最佳伙伴,而现在 NodeJS 有 MongoDB 做最佳的组合。MongoDB 是 NoSQL 的代表之一,其采用 JSON/BSON 当做数据储存和沟通的格式,亦使用 JavaScript 做为 Server-side 的执行程序语言(相当于传统 RDBMS 的预储程序),一切设计和习惯与 NodeJS 搭配使用起来,简直绝配。若你对 MongoDB 的一些基本操作有疑问,可以先参考旧文”MongoDB 快速笔记”。

使用 MongoDB

MongoDB 拥有 NoSQL 的普遍特色,不用预先定义 Schema,所有的 database 和 collection(相当于传统 RDBMS 的 Table),都会在新增数据后,自动被建立,我们只要专注于使用 NodeJS 操作数据库即可。

要在 NodeJS 里使用 MongoDB,可以安装 mongodb native driver,若透过 npm 来安装:

npm install mongodb

然后可以使用 NodeJS 建立 MongoDB connection pool ,做一些基础的操作:

var mongodb = require('mongodb');

var mongodbServer = new mongodb.Server('localhost', 27017, { auto_reconnect: true, poolSize: 10 });
var db = new mongodb.Db('mydb', mongodbServer);

/* open db */
db.open(function() {
    /* Select 'contact' collection */
    db.collection('contact', function(err, collection) {
        /* Insert a data */
        collection.insert({
            name: 'Fred Chien',
            email: 'cfsghost@gmail.com',
            tel: [
                '0926xxx5xx',
                '0912xx11xx'
            ]
        }, function(err, data) {
            if (data) {
                console.log('Successfully Insert');
            } else {
                console.log('Failed to Insert');
            }
        });

        /* Querying */
        collection.find({ name: 'Fred Chien' }, function(err, data) {
            /* Found this People */
            if (data) {
                console.log('Name: ' + data.name + ', email: ' + data.email);
            } else {
                console.log('Cannot found');
            }
        });
    });
});

注:这是 MongoDB 的基本常识,每当新增一笔数据,MongoDB 会自动帮该笔数据加上 _id 字段,并给与一个唯一值(格式是 ObjectId),所以我们不需要像过去 使用 SQL Server 一般,自己刻意去定义一个 ID 字段。

预设的 ObjectId 范围太小,改用 UUID 来当数据的唯一 ID

如果你过去有过 Web 开发经验,到这边肯定会开始有一些疑问欲求解,第一个问题肯定是”ObjectId 的数量极限?”。笔者在此不会回答这问题,因为这答案并不重要,想要准确知道答案,可以去”
mongodb.org“寻找答案。

比起上述问题,相信你应该更想问:

预设的 ObjectId 适用的范围?
如果日后数据库要扩展(Scale),是否有其他的 ID 解决方案可使用?

一般情况, MongoDB 预设的 ObjectId 就相当够用了,但如果你是要建构大型的 Web Service 或是保留未来的扩充性,可使用 UUID 去代替 ObjectId。不过,因为 MongoDB 本身并不生成 UUID,若是要使用 UUID,就必需先自行产生好 UUID,然后在新增数据时指定生成好的 UUID 给 _id 字段,让 MongoDB 改用我们给的 ID 而不使用预设生成的 ObjectId。

 

因为要自行产生 UUID,必需先为 NodeJS 安装模块 node-uuid:

npm install uuid

然后生成 UUID 并在 insert 时使用:

var uuid = require('node-uuid');
var mongodb = require('mongodb');

var mongodbServer = new mongodb.Server('localhost', 27017, { auto_reconnect: true, poolSize: 10 });
var db = new mongodb.Db('mydb', mongodbServer);

/* open db */
db.open(function() {
    /* Select 'contact' collection */
    db.collection('contact', function(err, collection) {

        /* Generate UUID(16 Bytes) and convert to BinaryData object for mongodb */
        var uuidBinary = new Buffer(uuid.v1({}, []));
        var id = mongodb.BSONPure.Binary(uuidBinary, mongodb.BSONPure.Binary.SUBTYPE_UUID);

        /* Insert a data with uuid */
        collection.insert({
            _id: id,
            name: 'Fred Chien',
            email: 'cfsghost@gmail.com'
        }, function(err, data) {
            if (data) {
                console.log('Successfully Insert');
            } else {
                console.log('Failed to Insert');
            }
        });
    });
});

你可能会发现,在上面的范例程序中,我们将 UUID 转成 MongoDB BSON 的 BinaryData 格式,这是为了效能考虑,因为用纯字符串当做 Unique ID,在数据库搜寻上会比 BinaryData Object 慢很多。

储存时间戳(Timestamp)

关于储存时间的问题,如果你去各大 MongoDB 讨论区询问或查询,通常大家都会告诉你不必做这件事,因为每一笔数据被建立后,自动产生的 ObjectId 就包含了建立的时间讯息,我们只要去学习如何从中去解析时间即可。但是,不单只是建立时间,有时我们会为数据加上各种不同的时间戳,如:更新时间等,所以,储存时间戳还是必要的。

虽然网络上相关 NodeJS 范例并不多,但 MongoDB 确实有 Timestamp 的数据结构可以用,我们可以这样使用:

var uuid = require('node-uuid');
var mongodb = require('mongodb');

var mongodbServer = new mongodb.Server('localhost', 27017, { auto_reconnect: true, poolSize: 10 });
var db = new mongodb.Db('mydb', mongodbServer);

/* open db */
db.open(function() {
    /* Select 'contact' collection */
    db.collection('contact', function(err, collection) {

        /* Generate Timestamp and convert for mongodb */
        var ts = new Date().getTime();
        var i = ts % 1000;
        var t = new mongodb.BSONPure.Timestamp(i, Math.floor(ts * 0.001));

        /* Insert a data with uuid */
        collection.insert({
            name: 'Fred Chien',
            email: 'cfsghost@gmail.com',
            created: t
        }, function(err, data) {
            if (data) {
                console.log('Successfully Insert');
            } else {
                console.log('Failed to Insert');
            }
        });
    });
});

建立数据库索引(Index)

过去有接触过数据库的人应该都很清楚,索引(Index)是能优化数据查询速度的重要功能,MongoDB 同样也有索引的设计。

可以在 NodeJS 中,这样为 name 字段加上索引:

collection.createIndex({ name: 1 });

后记

 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值