Realm Blog

Realm Node.js 发布:首个专门为 Node 开发的对象型数据库

Realm 非常专注于为移动开发者服务,因此我们现已搭建并开源了 Realm 移动端数据库的 Swift、Objective-C、Java、Xamarin 以及 React Native 版本。而今,我们要宣布一个与众不同的产品:Realm Node.js。我们确信这是首个专门为 Node 开发的对象型数据库 (Object Database),并且已经可以在 npm 上获取得到,只需要运行 npm install --save realm 即可,它是完全免费、也是完全开源的。

多年以来,我们收到了无数个移动开发者希望能够在服务器上运行 Realm 的请求,所以这项任务一直位于我们的代办列表当中,尽管优先级很低。不过,自 9 月份我们发布了新的 Realm 移动端平台之后,我们就很快改变了该任务的优先级,因为潜在用户们开始要求我们能够为这个平台提供 Node 接口。我们很快同意让 Node 成为平台产品战略的一部分(那几天还通过了很多决策),最终致使了 Realm Node.js 的诞生。

Realm Node.js 是什么?作用如何?

Realm 是一款对象型数据库。这意味着在开发过程当中,您只需要和此前一样使用对象进行开发即可,只不过这些对象都能够通过 Realm 简单、高效地存储到硬盘当中。您无需将这些对象序列化为 JSON 格式,也无需通过 ORM 将对象存储在数据库表当中。您可以坚持「面向对象开发」的准则,从而实现「所建即所得」。此前,在所有的移动客户端平台上都可以如此这般——如今服务器端的 Node.js 也可以这么做了!

对于移动开发者而言,Realm Node.js 意味着您可以创建一个内含数据的 Realm 数据库,然后发送给客户端,这在很多方面都是及其有用的,例如绕过应用程序的容量限制等等。这正是多年以来,移动开发者要求我们如此做的主要原因。

不过当我们向后端开发人员展示了一些早期版本之后,事情变得更有意思了,我们意识到:对于 Node 社区而言,这个功能似乎更加迫切、有用,这远远超出了我们此前的想象。例如,我们意识到在多个 Node 实例之间实时共享数据是非常有用的。为了进一步阐释这一点,我们提供了一个简单的演示:如何在同一台机器上的两个 Node 进程当中使用 Realm,从而能够让它们能够协同工作,而无需对两者共用的对象进行反复的序列化和反序列化。

Realm 的独特功能之一便是反应式架构 (reactive architecture)。在底层当中,Realm 使用了多版本并发控制机制 (Multiversion Concurrency Control),从而让数据库能够跨线程和进程实现并发访问。这意味着读取数据的一方永远不会阻塞数据的写入操作,并且读写双方均有一致的数据库快照——从而确保 Realm 满足 ACID 的要求。为了协调这一点,当写操作事务完成时,Realm 将使用通知系统来对访问器 (accessor) 进行更新。开发人员可以通过 Realm 的通知 API 来对这些变化做出反应。这个示例演示了 Node.js 开发者如何使用 Realm 提供的此功能来实现进程间通信,从而完成两个独立服务之间的数据相互同步。

在这个示例当中,我们使用了两个流行的 Node.js 库:Express (Web 框架) 和 Winston (日志库)。我们使用 Express 来创建 HTTP 终端 (endpoint),然后使用 Winston 来记录相关网络请求的信息:

var express = require('express'),
    util = require('util'),
    winston = require('winston');
    RealmWinston = require('./winston-realm').Realm;

var app = express();

// 使用自定义的 Winston 传输协议: RealmWinston
// 向 winston.realm 写入日志数据
winston.add(RealmWinston, {});

app.get('/', function (req, res) {
  res.send('Hello World!');
  winston.info('Handled Hello World');
});

app.use(function (req, res, next) {
  res.status(404).send('Sorry can not find that!');
  winston.error('404 Error at: ' + req.url);
})

app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});

为了体现 Realm 的优势所在,我们为 Winston 创建了一个自定义的传输协议,从而能够将日志数据存放到 Realm 文件当中。在基本路径 (base path) 当中,我们记录了一个确认了「Hello World」响应的内容消息。对于其他所有的路径而言,我们则使用 404 错误进行响应,并在错误消息当中记录对应的路径。在将日志数据存放到 Realm 文件之后,我们之后便可以启动另一个 Node 进程,然后注册一个 Realm 监听器 (listener) 来对更改做出反应:

'use strict';

var Realm = require('realm');

let winstonRealm = new Realm({
  path: 'winston.realm'
});

// 注册监听器,从而输出 error 级别的日志信息
winstonRealm.objects('Log').filtered('level = "error"').addListener((logs, changes) => {
  changes.insertions.forEach((index) => {
    let log = logs[index];
    console.log(log.message);
  })
});

监听器借助 Realm 对集合通知 (collection notifications) 的支持,从而能够将插入的对象、删除的对象或者被修改的对象所对应的索引,作为特定的变化情况传递出去。这个示例向一个检索所有 error 级别日志的查询当中添加了一个监听器,它会将日志消息输出到控制台当中。

尽管这个示例非常简单,但是这个做法还可以用于更为高级的场景当中,从而能够在不同的微服务 (microservice) 架构之间实现数据的同步。点击这里查看完整的演示示例。如果您准备好在自己的 Node.js 服务当中使用 Realm 的话,那么您可以在我们的 React Native 文档API 文档当中找到您所需要的全部内容(因为代码库是在我们所有的 JavaScript 平台之间共享的)。

那么您还可以使用 Realm Node.js 做什么呢?可以让应用能够使用比本地内存大得多的数据库!可以将其作为可检索 (queryable)、可观察 (observable) 的数据结构!可以在多个 Node 实例之间构建反应式架构!还可以实现 Docker 镜像之间的互相通信!您使用 Realm Node.js 完成了某些壮举,请告诉我们,我们很渴望听到您的想法!


Realm Team

At Realm, our mission is to help developers build better apps faster. We provide a unique set of tools and platform technologies designed to make it easy for developers to build apps with sophisticated, powerful features — things like realtime collaboration, augmented reality, live data synchronization, offline experiences, messaging, and more.

Everything we build is developed with an eye toward enabling developers for what we believe the mobile internet evolves into — an open network of billions of users and trillions of devices, and realtime interactivity across them all.

Receive news and updates from Realm straight to your inbox