《开源精选》是我们分享Github、Gitee等开源社区中优质项目的栏目,包括技术、学习、实用与各种有趣的内容。本期推荐的RxDB(Reactive Database的缩写)是一个NoSQL数据库,用于 JavaScript 应用程序,如网站、混合应用程序、电子应用程序、渐进式 Web 应用程序和 Node.js。

反应式意味着您不仅可以查询当前状态,还可以订阅所有状态更改,例如查询结果甚至文档的单个字段。这对于基于 UI 的实时应用程序来说非常有用,因为它易于开发并且具有巨大的性能优势。 为了在客户端和服务器之间复制数据,RxDB 提供了用于实时复制的模块,可以使用任何符合CouchDB的端点以及自定义GraphQL端点。

RxDB特征

对浏览器、nodejs、electron、cordova、react-native 和所有其他 javascript-runtime 的多平台支持基于RxJS的响应式数据处理离线优先让您的应用在用户没有互联网时仍然可以运行客户端和服务器数据之间的复制基于模式的json-schema易于学习的标准Mango-Query与您从 mongoDB 和 mongoose 中了解的完全一样加密单个数据字段以保护您的用户数据数据库状态 (json) 的导入/导出,非常适合使用TDD进行编码多窗口在不同的浏览器窗口或 nodejs 进程之间同步数据ORM 功能可轻松处理数据代码关系并自定义文档和集合的功能完整的TypeScript支持以实现快速安全的编码(需要 Typescript v3.8 或更高版本)

快速开始

安装 RxDB 库和 RxJS(如果之前没有安装)

npm install rxdb rxjs --save

使用 PouchDB RxStorage创建一个数据库(您也可以使用其他基于LokiJS或Dexie.js的存储)。

import { createRxDatabase } from rxdb;import { getRxStoragePouch, addPouchPlugin } from rxdb/plugins/pouchdb;addPouchPlugin(require(pouchdb-adapter-idb));const myDatabase = await createRxDatabase({name: heroesdb,storage: getRxStoragePouch(idb)});

为集合创建架构

const mySchema = {title: human schema,version: 0,primaryKey: passportId,type: object,properties: {passportId: {type: string,maxLength: 100 // <- the primary key must have set maxLength},firstName: {type: string},lastName: {type: string},age: {description: age in years,type: integer,// number fields that are used in an index, must have set minium, maximum and multipleOfminimum: 0,maximum: 150,multipleOf: 1}},required: [firstName, lastName, passportId],indexes: [age]}

将集合添加到数据库

const myCollections = await myDatabase.addCollections({humans: {schema: mySchema},});

插入文档

const myDocument = await myDatabase.humans.insert({passportId: foobar,firstName: Alice,lastName: Bobby,age: 42});

订阅文档值

myDocument.lastName$.subscribe(lastName => {console.log(lastName is now + lastName);});

查询一些文档

const foundDocuments = await myDatabase.humans.find({selector: {age: {$gt: 21}}}).exec();

订阅查询结果

myDatabase.humans.find({selector: {age: {$gt: 21}}}).$.subscribe(documents => {console.log(query has found + documents.length + documents);});

更新文档

// either via atomicUpdate()await myDocument.atomicUpdate(data => {data.lastName = Carol;return data;});// or via atomicPatch()await myDocument.atomicPatch({lastName: Carol});

删除文档

await myDocument.remove();

开发模式

dev-mode 插件为 RxDB 添加了许多检查和验证。这可确保您正确使用 RxDB API,因此在开发模式下使用 RxDB 时应始终使用开发模式插件。

为模式、查询、ORM 方法和文档字段添加验证检查。添加可读的错误消息。确保readonlyJavaScript 对象不会意外变异。

重要: : dev-mode 插件会增加你的构建大小并降低性能。它必须始终在开发中使用。你永远不应该在生产中使用它。

import { addRxPlugin } from rxdb;import { RxDBDevModePlugin } from rxdb/plugins/dev-mode;addRxPlugin(RxDBDevModePlugin);

与 Node.js 一起使用

async function createDb() {if (process.env.NODE_ENV !== "production") {await import(rxdb/plugins/dev-mode).then(module => addRxPlugin(module as any));}const db = createRxDatabase( /* ... */ );}

与 Angular 一起使用

import { isDevMode } from @angular/core;async function createDb() {if (isDevMode()){await import(rxdb/plugins/dev-mode).then(module => addRxPlugin(module as any));}const db = createRxDatabase( /* ... */ );// ...}

模式验证

RxDB 有多个插件可用于确保您的文档数据始终与提供的 JSON 模式匹配。

注意:模式验证可能会占用 CPU 资源并增加构建大小。您应该始终在开发模式下使用 scehma 验证插件。对于大多数用例,您不应在生产中使用验证插件。

当您插入或更新 aRxDocument或使用复制插件复制文档数据时,验证模块会执行模式验证。当不使用验证插件时,可以保护任何文档数据,但在保存不符合架构的数据时可能会出现未定义的行为。

证实

lidate插件使用is-my-json-valid进行模式验证。

import { addRxPlugin } from rxdb;import { RxDBValidatePlugin } from rxdb/plugins/validate;addRxPlugin(RxDBValidatePlugin);

ajv-验证

另一个执行模式验证的验证模块。这个使用ajv作为验证器,速度更快。更好地符合 jsonschema-standard,但也有更大的构建大小。

import { addRxPlugin } from rxdb;import { RxDBAjvValidatePlugin } from rxdb/plugins/ajv-validate;addRxPlugin(RxDBAjvValidatePlugin);

验证-z-模式

者is-my-json-valid和ajv-validate用于执行内容安全策略中不允许eval()时可能不需要的验证。unsafe-eval这个使用z-schema作为验证器,不使用eval.

import { addRxPlugin } from rxdb;import { RxDBValidateZSchemaPlugin } from rxdb/plugins/validate-z-schema;addRxPlugin(RxDBValidateZSchemaPlugin);

数据迁移

使用 RxDB,您可以为您的集合提供迁移策略,自动(或随叫随到)将现有数据从旧模式转换为新模式。这可确保客户的数据始终与您的最新代码版本相匹配。

添加迁移插件

要启用数据迁移,您必须添加migration插件。

import { addRxPlugin } from rxdb;import { RxDBMigrationPlugin } from rxdb/plugins/migration;addRxPlugin(RxDBMigrationPlugin);

提供策略

创建集合后,您必须在架构的版本号大于 时提供 migrationStrategies 0。为此,您必须将一个对象添加到migrationStrategies为每个模式版本分配一个函数的属性中。migrationStrategy 是一个函数,它获取旧文档数据作为参数并返回新的、转换后的文档数据。如果策略返回null,文档将被删除而不是迁移。

myDatabase.addCollections({messages: {schema: messageSchemaV1,migrationStrategies: {// 1 means, this transforms data from version 0 to version 11: function(oldDoc){oldDoc.time = new Date(oldDoc.time).getTime(); // string to unixreturn oldDoc;}}}});

也可以使用异步策略:

myDatabase.addCollections({messages: {schema: messageSchemaV1,migrationStrategies: {1: function(oldDoc){oldDoc.time = new Date(oldDoc.time).getTime(); // string to unixreturn oldDoc;},/*** 2 means, this transforms data from version 1 to version 2* this returns a promise which resolves with the new document-data*/2: function(oldDoc){// in the new schema (version: 2) we defined senderCountry as required field (string)// so we must get the country of the message-sender from the serverconst coordinates = oldDoc.coordinates;return fetch(http://myserver.com/api/countryByCoordinates/+coordinates+/).then(response => {const response = response.json();oldDoc.senderCountry=response;return oldDoc;});}}}});

您还可以筛选应迁移的文档:

myDatabase.addCollections({messages: {schema: messageSchemaV1,migrationStrategies: {// 1 means, this transforms data from version 0 to version 11: function(oldDoc){oldDoc.time = new Date(oldDoc.time).getTime(); // string to unixreturn oldDoc;},/*** this removes all documents older then 2017-02-12* they will not appear in the new collection*/2: function(oldDoc){if(oldDoc.time < 1486940585) return null;else return oldDoc;}}}});

—END—

开源协议:Apache-2.0 license

开源地址:

https://github.com/pubkey/rxdb
分类: 软件分享 标签: 暂无标签

评论

暂无评论数据

暂无评论数据

目录