Realm Blog

迎接实时性与扩展性:Realm 移动端平台 1.0 正式发布

by /

今天,我们在此非常自豪地宣布:Realm 移动端平台 (Mobile Platform) 1.0 稳定版现已正式发布!无论产品的规模如何,Realm 移动端平台都可以在任意一种实际产品当中使用。几个月以来,我们一直在努力地修复各种问题,不停地打磨我们的产品,优化代码,并且还添加了一些全新的功能(参见下文)。1.0 版本的发布,可谓是 Realm 全体员工的一个重要里程碑,我们非常感谢我们的客户和社区的全体成员,在我们测试版本发布之后,他们就不断反馈各式各样的意见来帮助我们来完善这个产品!

Realm 移动端平台使开发者能够更轻松地构建具有复杂功能的应用程序,例如提供实时协作 (realtime collaboration)、实时通讯 (live messaging) 以及强大的离线客户端体验等等。该平台将 iOS 和 Android 平台上最受欢迎的客户端数据库——Realm,与我们全新的 Realm 对象服务器 (Object Server) 结合在一起,从而提供了实时数据自动同步的功能。对于开发者而言,您无需编写或者维护任何的后台代码,也不必再去对后台传来的数据做任何的序列化操作,Realm 会自动帮您完成所有的同步操作——这样您就可以确保设备上的数据始终与服务器上的数据完全同步!Realm 还可以轻松地创建服务器端的逻辑代码,以便让服务器能够即时地对数据变更做出响应,同时也可以与既有的系统以及 API 进行集成。

在这个发布版本当中,我们平台所有的三个版本都已就绪,您可以即刻开始构建相关的应用程序。此外,我们也提供了一些有趣的演示代码,您可以运行它们来体验一下我们平台的功能。阅读此文以获取更多细节……或者,如果您打算深入了解我们平台的话,只需要下载我们的 演示应用:Draw,搭建好基于 Mac 或者 Linux 平台的免费开发者版本后,就可以开始探索啦!

三个全新的企业版功能

在这个发布版本当中,我们还为企业版带来了三个全新的功能:

数据集成 API

我们全新的数据集成 (Data Integration) API 允许开发者轻松地将 Realm 移动端平台与其他任意一种数据源进行集成,这使得开发者能够基于既有的数据和服务,简单地使用 Realm 来为应用提供实时性以及其他应用特性。我们的许多测试版用户利用这个全新的 Realm 功能,将他们既有的系统和资源「调集」起来,借助 Realm 这个桥梁来提供实时性功能,从而让他们的 Android 和 iOS 团队能够轻松地构建现代化的、能够快速响应用户交互的应用程序,并且这些应用还能够对接到既有系统的数据和逻辑当中。

例如,假设有一家零售商,它想要为客户带来全新的移动购物体验,但是它还需要将新的应用无缝地对接到既有的支付业务数据库当中。借助 Realm 这个全新的数据集成 API,Realm 能够可靠地将既有数据库连接到 Realm 对象服务器,以便对象服务器能够和支付业务数据库同步数据。为了确保所有地方数据的准确性,我们的这个 API 将会对断开的链接进行分析,并在可行的时候重新启动中断的事务操作。有了这些保证,Realm 对象服务器便可以作为客户端数据库和支付业务数据库之间的中间件,使得这家零售商能够利用 Realm 在既有数据库的基础上来构建全新的项目。

数据集成 API 可以轻松地构建自定义连接器 (connector),但是我们同样也发布了我们首个预构建的连接器,其专门适用于 PostgreSQL。我们正在与其他组织共同努力,并且基于我们客户的要求,我们预计很快将推出专门适用于 Oracle、MongoDB、Hadoop、SAP HANA 以及 Redis 的预构建连接器。

横向扩展性

我们所构建的 Realm 平台是非常稳定的:一般而言,单个 Realm 对象服务器可以同时处理超过一万个用户的并发操作,这个数据会根据您应用的实际情况和平台所运行的硬件有所不同。但是,为了让客户能够实现大规模扩展,我们在企业版当中提供了横向扩展 (horizontal scaling) 功能。这其中包括了一个内置的负载均衡,它能够自动处理并对连接进行分发。这使得用户可以并行部署多个 Realm 对象服务器实例,这样您的应用便可以支持超过 100 万个用户的实时并发操作。

持续备份

持续备份允许您在灾备服务器上进行自动备份,以保存生产环境下的对象服务器数据。在发生灾难(断电、硬件故障、自然灾害等)的时候,您可以立即切换到灾备服务器,以便能够继续对应用进行操作。开发者可以选择灾备服务器的位置,当然我们支持不同的区域,这样可以提高灾难恢复的能力。

企业版当中的新功能

Realm 使用入门与示例应用:Draw

首先,您需要安装 Realm 平台,您可以选择在自己的机器上安装,也可以在您自己选择的云服务器上安装。除非您对事件处理 (event handling) 或者其他专业版的功能有着强烈兴趣,我们还是建议您首先从开发版本开始了解——因为开发版已足够强大,并且完全免费、没有时间限制,您完全可以借助它来构建一款具备实时功能的应用(在此参见许可条款)。我们的文档会引导您完成安装,做好相应的配置,最终能够成功运行。

一旦您完成了 Realm 的安装,您就可以开始运行示例代码了。Draw 是一款白板协作应用,它展示了 Realm 是如何处理多用户之间的实时数据同步的。它是完全开源的,并且它与 Realm 的其他演示一起,都可在 Github 上获取得到。Draw 的这个视频展示了两个 iPad 之间的实时数据同步操作,并且当网络暂时中断的时候,Realm 是如何处理的。

了解更多

如果您想要深入了解 Realm 移动端平台,或者想要进行提问的话,我们的产品团队会在 1 月 31 日(周二)举办一场在线技术讲座。您可以前往此处进行注册

Read more

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

by /

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 完成了某些壮举,请告诉我们,我们很渴望听到您的想法!

Read more

Realm 移动端平台发布:实时同步的 Realm 和完全开源的数据库实现

by /

自 2014 年我们推出 Realm 以来,我们就一直秉持着一个目标:提供一款强大的、用以替代 SQLite 和 Core Data 的产品,从而帮助移动开发者们更好、更快地搭建移动应用。时光荏苒,两年半之后,我们已经拥有了十万以上的活跃开发者,并且在全球范围内,使用 Realm 的应用下载量已经突破了十亿次。我们非常感激开发者社区的支持和反馈,正是如此才使得我们能有今日的成就。但我们需要做的还有很多。

今天,我们推出了 Realm 移动端平台 (Realm Mobile Platform, RMP),这是一款全新的产品,它集成了我们完全开源的(参见下文)iOS 和 Android 客户端数据库,并且借助新的服务端技术,它还能够提供实时同步 (Realtime Synchronization)、冲突处理 (Conflict Resolution) 以及响应式事件处理 (Reactive Event Handling)。 RMP 让移动开发者们能够实现此前难以构建的功能,比如说提供实时协作 (Realtime Collaboration)、实时通信、离线缓存体验 (Offline-first) 等诸如此类的功能。

 

新平台现已推出了两种类型的 beta 版本,现在即可使用!开发者版本 (Developer Edition) 将永久免费,它适用于绝大多数简单的适用情形,业余爱好者到小型商业应用都可以使用这个版本。企业版 (Enterprise Edition) 提供了一段试用期,能够完全支持大型产品。具体详情将在下文进行介绍。虽然目前平台只支持 Java、Objective-C 和 Swift,但是 React Native 和 Xamarin 版本也即将上线。

我们同时还做了一个重大的决定:我们非常自豪地宣布 Realm Core 模块现已开源,这让我们的 Realm 移动平台将全面拥抱开源——您可以在这个 repo 当中找到相应的源码。无论是作为新平台的一个重要组成部分,还是作为移动开发者的一个独立数据库选择,移动数据库这个领域对我们来说是非常重要的,因此我们的工程团队将继续致力于维护和改善 Realm Java、Realm Objective-C、Realm React Native、Realm Swift 和 Realm Xamarin。

The Realm Mobile Platform

无处不「对象」

即便是长期使用 Realm 的用户,都很可能没有意识到,Realm 是一个内核级别的嵌入式对象数据库,但是这只是其中一个我们与其他数据库的主要区别。实际上,是因为开发者喜爱 Realm 的易用和高速才成就了这一切。开发者们不用去处理复杂的对象关系映射,他们只需要处理对象即可——也就是说,数据库 即是 数据模型。

我们在新的对象服务器 (Object Server) 当中扩大了我们这方面的设计理念,也就是我们平台内部的一个非常重要的神奇概念——我们称之为「实时对象」(Live Objects)。实时对象意味着设备上的数据对象总是能与服务器上的数据对象完全 保持同步。这个同步操作将会自行完成,并且是无缝的——这意味着开发者不必去撰写网络层代码——并且只有当对象发生变化时才会进行网络同步,而不是所有的数据对象都去进行网络同步,这使得这个同步操作非常地高效。Realm 平台同样也会进行冲突处理,因此对某个共享的实时对象进行同时修改也能确切地得到解决。平台将会自动执行默认的预设处理规则,而这种模式对于绝大多数情况来说都是适用的;然而,您也可以轻松地创建自定义冲突解决规则。

借助 Realm,您完全不需要考虑网络层的工作。您只需要大胆地构建与实时对象进行交互的应用即可。这意味着所有那些难以构建的特性,例如实时协作、实时通信将会变得无比容易。试想,如果要允许用户通过不同的设备在一块共享的白板上进行协同工作的话,最难的部分在于要确保所有的更改操作都要立即反应在每个用户的 UI 上面,而且如果发生了冲突——例如用户同时对某个地方进行了绘制或者擦除操作,那么这个冲突会很优雅地被处理掉。Realm 平台都为您提供了现成的解决方案。

使用 Realm 移动平台构建离线缓存体验

Realm 平台对于带有离线缓存的应用来说,同样也提供了良好的解决方案,因为在网路连接断开或者时断时续的情况下,第一要务是要提供一个无缝的用户体验。Realm 移动平台正好为设备提供了一个非常高效的嵌入式数据库,因此即便网络连接丢失,您的应用仍然能够保持良好的用户体验。这正是使用 Realm 移动数据库的一个重要优势所在。

但是如果您使用了整个 Realm 平台——Realm 数据库加上对象服务器的话——那么您能够实现的功能将会更多。首先,由于双向的同步操作会在后台自动进行,因此您可以确保设备上的数据对象在网络连接丢失之前,是完全与服务器同步了的。当网络连接恢复之后,同步操作又会自动进行,而这个时候任何可能发生的冲突都将被自动解决——实时对象又再一次地完全同步。您的用户就可以继续工作了,甚至他可能都没有意识到网络连接出现了异常。

事件处理

Realm 平台的企业版同样也包含了另一个关键特性:服务器端事件处理框架,这个框架提供了一个需求管道 (plumbing),每当对象发生改变,就可以轻易地触发服务器端的逻辑操作。您可以对这个框架进行配置,让其能够监听移动端上的对 象变化情况,然后立即在服务器端运行某些代码作为回应。例如,当用户填写订购单的时候,他/她在输入框中键入了优惠券代码。这个时候,设备端的优惠券对象所发生的变化将会被框架所捕获,接下来这个变化就会立刻同步到服务器当中 。这个特定的变化将会致使事件处理框架触发对优惠券代码的检查操作,以确保这是一个合法的代码,随后检查之后的合法性将会更新到服务器端的优惠券对象当中。再然后这个网络回应便会同步回客户端的优惠券对象,随后触发一个通知,进行 UI 的更新操作。

Event handling

您可以使用事件处理来与现有的 API 或者基础功能进行集成,这使得 Realm 对象服务器将作为 API 桥接器 (Bridge) 或者作为移动中间件 (Mobilization Middleware) 来使用。这个功能同样也允许您基于「无服务器 (serverless)」的计 算原则来设计应用——您可以为每一个单独的函数编写特定的触发操作。

如何入门

Realm 移动平台现已推出了两个版本。开发者版本将永久免费,现已推出了 beta 测试版。开始使用这个版本是非常容易的,我们非常期待您的反馈。企业版则包含了事件处理框架、简单集成等其他重要的功能。它目前正在内测当中,但是只需简单填写一个表单 ,便能够加入到我们的内测计划当中来。

Read more

在13949次代码提交、6148个问题关闭之后:Realm 发布1.0版本,感谢大家的支持

by /

2014年7月我们发布了 Realm —— 首个为移动端定制的数据库。今天,在13949次代码提交、6148个问题关闭之后,我们骄傲地宣布 Realm 1.0 版本发布。感谢广大 iOS 和 Andorid 开发社区对 Realm 的帮助。

起初,我们只为 iOS 和 Mac 开发者提供 Realm Objective-C,后来又添加了对 Swift 和 Android 的支持。最近还发布了支持 React Native 和 Xamarin 的版本。到目前为止,Realm 已经支持所有主流移动平台和开发语言。这次发布不仅体现了 Realm 两年的点滴积累,也得益于开发社区的大力支持。再次感谢开发社区!👏

在发布1.0版本之前,Realm 就已经被广大开发者社区所接受。Realm 的 GitHub 仓库总计获得了超过12000个星标(还在持续增加中)。Realm 正在被超过10万个活跃开发者使用,数万个 app 由 Realm 提供数据库支持。这包括许多大型的公司例如星巴克、Twitter、 Anheuser-Busch、NBCUniversal、阿里巴巴、 eBay 等等。Realm 帮助开发者更便捷地提供更好的用户体验,从而创造出更好的 app。1.0版本的发布更是让开发者相信 Realm 进入了一个更成熟和稳定的阶段。

我们的修改记录 Java Objective-C 和 Swift 保存了这两年期间大大小小的改动。

什么是 Realm?

Realm 不是 ORM,也不基于 SQLite 创建,而是为移动开发者定制的全功能数据库。它可以将原生对象直接映射到我们开发的数据库引擎(远不仅是一个键值对存储)中。你可以使用 Realm 存储复杂的对象、操作对象间的关系,还可以进行高级的查询。

// Define you model class by extending RealmObject
public class Dog extends RealmObject {
    private String name;
    private int age;

    // ... Generated getters and setters ...
}

public class Person extends RealmObject {
    @PrimaryKey
    private long id;
    private String name;
    private RealmList<Dog> dogs; // Declare one-to-many relationships

    public Person(long id, String name) {
        this.id = id;
        this.name = name;
    }

    // ... Generated getters and setters ...
}

// Use them like regular java objects
Dog dog = new Dog();
dog.setName("Rex");
dog.setAge(1);

// Create a RealmConfiguration that saves the Realm file in the app's "files" directory.
RealmConfiguration realmConfig = new RealmConfiguration.Builder(context).build();
Realm.setDefaultConfiguration(realmConfig);

// Get a Realm instance for this thread
Realm realm = Realm.getDefaultInstance();

// Query Realm for all dogs younger than 2 years old
final RealmResults<Dog> puppies = realm.where(Dog.class).lessThan("age", 2).findAll();
puppies.size(); // => 0 because no dogs have been added to the Realm yet

// Persist your data in a transaction
realm.beginTransaction();
final Dog managedDog = realm.copyToRealm(dog); // Persist unmanaged objects
Person person = realm.createObject(Person.class); // Create managed objects directly
person.getDogs().add(managedDog);
realm.commitTransaction();

// Listeners will be notified when data changes
puppies.addChangeListener(new RealmChangeListener<RealmResults<Dog>>() {
    @Override
    public void onChange(RealmResults<Dog> results) {
        // Query results are updated in real time
        puppies.size(); // => 1
    }
});

// Asynchronously update objects on a background thread
realm.executeTransactionAsync(new Realm.Transaction() {
    @Override
    public void execute(Realm bgRealm) {
        Dog dog = bgRealm.where(Dog.class).equals("age", 1).findFirst();
        dog.setAge(3);
    }
}, new Realm.Transaction.OnSuccess() {
    @Override
    public void onSuccess() {
      // Original queries and Realm objects are automatically updated.
      puppies.size(); // => 0 because there are no more puppies younger than 2 years old
      managedDog.getAge();   // => 3 the dogs age is updated
    }
});
// Define your models like regular Objective‑C classes
@interface Dog : RLMObject
@property NSString *name;
@property NSData   *picture;
@property NSInteger age;
@end
@implementation Dog
@end
RLM_ARRAY_TYPE(Dog)
@interface Person : RLMObject
@property NSString             *name;
@property RLMArray<Dog *><Dog> *dogs;
@end
@implementation Person
@end

// Use them like regular Objective‑C objects
Dog *mydog = [[Dog alloc] init];
mydog.name = @"Rex";
mydog.age = 1;
mydog.picture = nil; // properties are nullable
NSLog(@"Name of dog: %@", mydog.name);

// Query Realm for all dogs less than 2 years old
RLMResults<Dog *> *puppies = [Dog objectsWhere:@"age < 2"];
puppies.count; // => 0 because no dogs have been added to the Realm yet

// Persist your data easily
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
  [realm addObject:mydog];
}];

// Queries are updated in real-time
puppies.count; // => 1

// Query and update the result in another thread
dispatch_async(dispatch_queue_create("background", 0), ^{
  Dog *theDog = [[Dog objectsWhere:@"age == 1"] firstObject];
  RLMRealm *realm = [RLMRealm defaultRealm];
  [realm beginWriteTransaction];
  theDog.age = 3;
  [realm commitWriteTransaction];
});
// Define your models like regular Swift classes
class Dog: Object {
  dynamic var name = ""
  dynamic var age = 0
}
class Person: Object {
  dynamic var name = ""
  dynamic var picture: NSData? = nil // optionals supported
  let dogs = List<Dog>()
}

// Use them like regular Swift objects
let myDog = Dog()
myDog.name = "Rex"
myDog.age = 1
print("name of dog: \(myDog.name)")

// Get the default Realm
let realm = try! Realm()

// Query Realm for all dogs less than 2 years old
let puppies = realm.objects(Dog).filter("age < 2")
puppies.count // => 0 because no dogs have been added to the Realm yet

// Persist your data easily
try! realm.write {
  realm.add(myDog)
}

// Queries are updated in real-time
puppies.count // => 1

// Query and update from any thread
dispatch_async(dispatch_queue_create("background", nil)) {
  let realm = try! Realm()
  let theDog = realm.objects(Dog).filter("age == 1").first
  try! realm.write {
    theDog!.age = 3
  }
}
// Define your models and their properties
class Car {}
Car.schema = {
  name: 'Car',
  properties: {
    make:  'string',
    model: 'string',
    miles: 'int',
  }
};
class Person {}
Person.schema = {
  name: 'Person',
  properties: {
    name:    {type: 'string'},
    cars:    {type: 'list', objectType: 'Car'},
    picture: {type: 'data', optional: true}, // optional property
  }
};

// Get the default Realm with support for our objects
let realm = new Realm({schema: [Car, Person]});

// Create Realm objects and write to local storage
realm.write(() => {
  let myCar = realm.create('Car', {
    make: 'Honda',
    model: 'Civic',
    miles: 1000,
  });
  myCar.miles += 20; // Update a property value
});

// Query Realm for all cars with a high mileage
let cars = realm.objects('Car').filtered('miles > 1000');

// Will return a Results object with our 1 car
cars.length // => 1

// Add another car
realm.write(() => {
  let myCar = realm.create('Car', {
    make: 'Ford',
    model: 'Focus',
    miles: 2000,
  });

// Query results are updated in real-time
cars.length // => 2
// Define your models like regular C# classes
public class Dog : RealmObject 
{
    public string Name { get; set; }
    public int Age { get; set; }
    public Person Owner { get; set; }
}

public class Person : RealmObject 
{
    public string Name { get; set; }
    public RealmList<Dog> Dogs { get; } 
}

var realm = Realm.GetInstance();

// Use LINQ to query
var puppies = realm.All<Dog>().Where(d => d.Age < 2);

puppies.Count(); // => 0 because no dogs have been added yet

// Update and persist objects with a thread-safe transaction
realm.Write(() => 
{
    var mydog = realm.CreateObject<Dog>();
    mydog.Name = "Rex";
    mydog.Age = 1;
});

// Queries are updated in real-time
puppies.Count(); // => 1

// LINQ query syntax works as well
var oldDogs = from d in realm.All<Dog>() where d.Age > 8 select d;

// Query and update from any thread
new Thread(() =>
{
    var realm2 = Realm.GetInstance();

    var theDog = realm2.All<Dog>().Where(d => d.Age == 1).First();
    realm2.Write(() => theDog.Age = 3);
}).Start();

为什么使用 Realm?

简单

易用性是 Realm 的主要目标。开发者反馈说他们只用花费数小时就将大型应用的数据存储迁移到了 Realm。一般来说,Realm 能在实现、优化和调试上节约数周时间。

快速

Realm 的易用性并不以牺牲性能为代价。我们的引擎通过使用内存映射(memory mapping)、懒加载(lazy loading)使得其访问速度优于 SQLite。尽管数据库性能比较往往根据实际情况而有所差异,但仍有很多开发者反馈 Realm 带来了巨大的性能提升。

跨平台

Realm 支持 JavaObjective-CReact NativeSwiftXamarin。你可以在不同平台访问同一个 Realm 文件,使用相同的数据模型定义,编写相似的业务逻辑。你更可以使用 Realm Browser 来打开 Realm 文件进行调试。

高级特性

Realm 对象永远与底层数据保持同步,这种机制很适合响应式编程和无方向的数据流。你可以在多个 Realm 对象间建立关系、使用高级的查询、信赖内置的 AES256 数据加密,以及为集成 Realm 数据与 UI 控件而开发的各种扩展。

信任

在大型 app 中使用 Realm?用户量很大?没问题,Realm 已经在生产环境中使用了很长一段时间。这其中包括一些大型的银行、健康顾问提供商和复杂的企业应用。同时还有许多 Apple App Store 和 Google Play Store 中的热门应用在使用 Realm。

社区驱动

Realm 是 GitHub 上的开源项目,需求往往来自社区反馈,并且我们十分欢迎贡���代码。GitHub 上的12000多个星标、数百个基于 Realm 的 app 和各种组件,使用 Realm 的时候,你永远不会觉得孤单。

支持

技术支持和 Bug 修正永远是 Realm 工程师的首要任务。你可以通过 Stack Overflow 得到来自 Realm 工程师的答案。

谁在使用 Realm?

亿万人在使用基于 Realm 的 app。

Twitter

最流行的 app 信任 Realm。Twitter 的创新视频应用 Vine 和它的2亿用户从2016年开始使用 Realm。

星巴克

这家财富500强中的零售商在它的旗舰 app 中使用 Realm,使你更方便地得到中意的饮品。

阿里巴巴

这家纽约证券交易所上市的中国巨无霸公司在他的 B2B 应用中使用 Realm。去年供应商和采购方在其平台上的交易创造了30亿美元的利润。

百威

这家巨型啤酒厂在他们的 TapWiser 应用中使用 Realm。酒吧和商店可以快速地通过手机订货而不需使用电脑。

SAP

如果你是 Concur 的用户,那么你已经在使用 Realm 了。这个拥有2万客户的应用给3千万员工提供财务报销服务。

Rite Aid

这个美国的财富500强零售业巨头在它的 EnvisionRx 应用中使用 Realm, 以帮助消费者们安全地存储数据。

Realm 的用户还包括:亚马逊、eBay、谷歌、GoPro、沃尔玛、阿迪达斯、思科、NBCUniversal、耐克、NFL等等。

接下来

如果你需要帮助请在 StackOverflow 上提问。

关注我们的微博获得最新的中文讯息。

开始使用 Realm Java - GitHub 项目页面
开始使用 Realm Objective-C - GitHub 项目页面
开始使用 Realm Swift - GitHub 项目页面
开始使用 Realm React Native - GitHub 项目页面
开始使用 Realm Xamarin - GitHub 项目页面

我们等不及想看看大家都能用 Realm 创造出什么!

Read more