Skip to content
/ rxdb Public

A fast, local first, reactive Database for JavaScript Applicationshttps://rxdb.info/

License

Notifications You must be signed in to change notification settings

pubkey/rxdb

Repository files navigation


JavaScript Database

A fast, local-first, reactive Database for JavaScript Applications


What is RxDB?

RxDB (short forReactiveDatabase) is alocal-first,NoSQL-database for JavaScript Applications like Websites, hybrid Apps, Electron-Apps, Progressive Web Apps, Deno andNode.js. Reactive means that you can not only query the current state, butsubscribeto all state changes like the result of a query or even a single field of a document. This is great for UI-basedrealtimeapplications in a way that makes it easy to develop and also has great performance benefits but can also be used to create fast backends in Node.js.
RxDB provides an easy to implementprotocolfor realtimereplicationwith your existing infrastructure or one of the plugins forHTTP,GraphQL,CouchDB,Websocket,WebRTC,Supabase,Firestore,NATS.
RxDB is based on a storage interface that enables you to swap out the underlying storage engine. This increasescode reusebecause you can use the same database code for different JavaScript environments by just switching out the storage settings.

Use thequickstart,read thedocumentationor explore theexample projects.

Multiplayer realtime applications

realtime.gif

Replicate with yourexisting infrastructure

RxDB provides an easy to implement,battle-testedreplication protocolfor realtime sync with your existing infrastructure.
There are also plugins to easily replicate withGraphQL,CouchDB,Websocket,WebRTC,Supabase,FirestoreorNATS.

Flexiblestorage layer

RxDB is based on astorage interfacethat enables you to swap out the underlying storage engine. This increasescode reusebecause the same database code can be used in different JavaScript environments by just switching out the storage settings.

You can use RxDB on top ofIndexedDB,OPFS,LokiJS,Dexie.js,in-memory,SQLite,in aWebWorkerthread and even on top ofFoundationDBandDenoKV.

No matter what kind of runtime you have, as long as it runs JavaScript, it can run RxDB:

Quick start

Install

npm install rxdb rxjs --save

Store data

import{
createRxDatabase
}from'rxdb/plugins/core';

/**
* For browsers, we use the dexie.js based storage
* which stores data in IndexedDB in the browser.
* In other JavaScript runtimes, we can use different storages:
* @link https://rxdb.info/rx-storage.html
*/
import{getRxStorageDexie}from'rxdb/plugins/storage-dexie';

// create a database
constdb=awaitcreateRxDatabase({
name:'heroesdb',// the name of the database
storage:getRxStorageDexie()
});

// add collections
awaitdb.addCollections({
heroes:{
schema:mySchema
}
});

// insert a document
awaitdb.heroes.insert({
name:'Bob',
healthpoints:100
});

Query data once

constaliveHeroes=awaitdb.heroes.find({
selector:{
healthpoints:{
$gt:0
}
}
}).exec();// the exec() returns the result once

Observe a Query

awaitdb.heroes.find({
selector:{
healthpoints:{
$gt:0
}
}
})
.$// the $ returns an observable that emits each time the result set of the query changes
.subscribe(aliveHeroes=>console.dir(aliveHeroes));

Continue with thequickstart here.

More Features (click to toggle)

Subscribe to events, query results, documents and event single fields of a document

RxDB implementsrxjsto make your data reactive. This makes it easy to always show the real-time database-state in the dom without manually re-submitting your queries. You can also addcustom reactiveness librarieslike signals or other state management.

db.heroes
.find()
.sort('name')
.$// <- returns observable of query
.subscribe(docs=>{
myDomElement.innerHTML=docs
.map(doc=>'<li>'+doc.name+'</li>')
.join();
});

reactive.gif

MultiWindow/Tab

RxDB supports multi tab/window usage out of the box. When data is changed at one browser tab/window or Node.js process, the change will automatically be broadcasted to all other tabs so that they can update the UI properly.

multiwindow.gif

EventReduce

One big benefit of having a realtime database is that big performance optimizations can be done when the database knows a query is observed and the updated results are needed continuously. RxDB internally uses theEvent-Reduce algorithm.This makes sure that when you update/insert/remove documents, the query does not have to re-run over the whole database but the new results will be calculated from the events. This creates a huge performance-gain with zero cost.

Use-Case-Example

Imagine you have a very big collection with many user-documents. At your page you want to display a toplist with users which have the mostpointsand are currently logged in. You create a query and subscribe to it.

constquery=usersCollection.find().where('loggedIn').eq(true).sort('points');
query.$.subscribe(users=>{
document.querySelector('body').innerHTML=users
.reduce((prev,cur)=>prev+cur.username+'<br/>','');
});

As you may detect, the query can take very long time to run, because you have thousands of users in the collection. When a user now logs off, the whole query will re-run over the database which takes again very long.

awaitanyUser.incrementalPatch({loggedIn:false});

But not with the EventReduce. Now, when one user logs off, it will calculate the new results from the current results plus the RxChangeEvent. This often can be done in-memory without making IO-requests to the storage-engine. EventReduce not only works on subscribed queries, but also when you do multiple.exec()'s on the same query.

Schema

Schemas are defined viajsonschemaand are used to describe your data.

constmySchema={
title:"hero schema",
version:0,// <- incremental version-number
description:"describes a simple hero",
primaryKey:'name',// <- 'name' is the primary key for the collection, it must be unique, required and of the type string
type:"object",
properties:{
name:{
type:"string",
maxLength:30
},
secret:{
type:"string",
},
skills:{
type:"array",
maxItems:5,
uniqueItems:true,
item:{
type:"object",
properties:{
name:{
type:"string"
},
damage:{
type:"number"
}
}
}
}
},
required:["color"],
encrypted:["secret"]// <- this means that the value of this field is stored encrypted
};
Mango / Chained queries

RxDB can be queried by standard NoSQL mango queries like you maybe know from other NoSQL Databases likemongoDB.

Also you can use thequery-builder pluginto create chained mango-queries.

// normal query
myCollection.find({
selector:{
name:{
$ne:'Alice'
},
age:{
$gt:67
}
},
sort:[{age:'desc'}],
limit:10
})

// chained query
myCollection
.find()
.where('name').ne('Alice')
.where('age').gt(18).lt(67)
.limit(10)
.sort('-age')
.exec().then(docs=>{
console.dir(docs);
});
Encryption

By setting a schema-field toencrypted,the value of this field will be stored in encryption-mode and can't be read without the password. Of course you can also encrypt nested objects. Example:

{
"title":"my schema",
"properties":{
"secret":{
"type":"string",
"encrypted":true
}
},
"encrypted":[
"secret"
]
}
Import / Export

RxDB lets you import and export the whole database or single collections into json-objects. This is helpful to trace bugs in your application or to move to a given state in your tests.

// export a single collection
constjsonCol=awaitmyCollection.dump();

// export the whole database
constjsonDB=awaitmyDatabase.dump();

// import the dump to the collection
awaitemptyCollection.importDump(json);


// import the dump to the database
awaitemptyDatabase.importDump(json);
Key-Compression

Depending on which adapter and in which environment you use RxDB, client-side storage islimitedin some way or the other. To save disc-space, RxDB uses a schema basedkeycompressionto minimize the size of saved documents. This saves about 40% of used storage.

Example:

// when you save an object with big keys
awaitmyCollection.insert({
firstName:'foo'
lastName:'bar'
stupidLongKey:5
});

// key compression will internally transform it to
{
'|a':'foo'
'|b':'bar'
'|c':5
}

// so instead of 46 chars, the compressed-version has only 28
// the compression works internally, so you can of course still access values via the original key.names and run normal queries.
console.log(myDoc.firstName);
// 'foo'

And for any other use case, there aremany more plugins and addons.

Get started

Get started now byreading the docsor exploring theexample-projects.

Support and Contribute

More content

Angular Database,Frontend Database,localStorage,React Database,Browser Database,React Native Database,PWA Database,In-memory NoSQL database,JSON database