PE PERSIS ISTIN ING G DATA WIT ITH REALM MOBIL ILE DATABASE
PE PERSIS ISTIN ING G DATA WIT ITH REALM MOBIL ILE DATABASE - - PowerPoint PPT Presentation
PE PERSIS ISTIN ING G DATA WIT ITH REALM MOBIL ILE DATABASE - - PowerPoint PPT Presentation
PE PERSIS ISTIN ING G DATA WIT ITH REALM MOBIL ILE DATABASE Adam Fisher Application Developer Integrated Web & Mobile Solutions Team CareSource Xamarin Certified Mobile Developer May 2015 May 2016 July 2017 July
Adam Fisher
- Application Developer
Integrated Web & Mobile Solutions Team CareSource
- Xamarin Certified Mobile Developer
- May 2015 – May 2016
- July 2017 – July 2018
- Author of the Xamarin Forms Video Player component
- Worked with for 8 months in Chicago
- Currently working on the CareSource mobile app
@calmtuna @adamgfisher /adamfisher
Outline
- Existing Mobile Persistence Solutions
- Benefits of a Mobile Database
- What is Realm?
- Code Examples
- Questions
Existing Persistence Solutions
KEY/VALUE STORAGE
- iOS:
NSUserDefaults
- Android:
SharedPreferences
- React Native: AsyncStorage
- Xamarin:
Xamarin.Essentials DATABASE STORAGE
Realm SQLite
Object Oriented Database Relational Database Cross-Platform Cross-Platform Objects Tables, Indexes, Views Remote Cloud Sync
X
Built-in Encryption
X
Live Objects
X
await AsyncStorage.setItem(’ApplicationData', '{ "data": [ { "id": 1, "name": "Bitcoin", "symbol": "BTC", "website_slug": "bitcoin" }, { "id": 2, "name": "Litecoin", "symbol": "LTC", "website_slug": "litecoin" }, { "id": 3, "name": "Namecoin", "symbol": "NMC", "website_slug": "namecoin" }, { "id": 4, "name": "Terracoin", "symbol": "TRC", "website_slug": "terracoin" }, { "id": 5, "name": "Peercoin", "symbol": "PPC", "website_slug": "peercoin" }, { "id": 6, "name": "Novacoin", "symbol": "NVC", "website_slug": "novacoin" }, { "id": 8, "name": "Feathercoin", "symbol": "FTC", "website_slug": "feathercoin" }, { "id": 9, "name": "Mincoin", "symbol": "MNC", "website_slug": "mincoin" }, { "id": 10, "name": "Freicoin", "symbol": "FRC", "website_slug": "freicoin" }, { "id": 13, "name": "Ixcoin", "symbol": "IXC", "website_slug": "ixcoin" }, { "id": 14, "name": "BitBar", "symbol": "BTB", "website_slug": "bitbar" }, { "id": 16, "name": "WorldCoin", "symbol": "WDC", "website_slug": "worldcoin" }, { "id": 18, "name": "Digitalcoin", "symbol": "DGC", "website_slug": "digitalcoin" }, { "id": 25, "name": "GoldCoin", "symbol": "GLD", "website_slug": "goldcoin" }, { "id": 31, "name": "Argentum", "symbol": "ARG", "website_slug": "argentum" }, { "id": 32, "name": "Fastcoin", "symbol": "FST", "website_slug": "fastcoin" }, { "id": 34, "name": "Bitgem", "symbol": "BTG", "website_slug": "bitgem" }, { "id": 35, "name": "Phoenixcoin", "symbol": "PXC", "website_slug": "phoenixcoin" }, { "id": 37, "name": "Megacoin", "symbol": "MEC", "website_slug": "megacoin" }, { "id": 41, "name": "Infinitecoin", "symbol": "IFC", "website_slug": "infinitecoin" }, { "id": 42, "name": "Primecoin", "symbol": "XPM", "website_slug": "primecoin" }, { "id": 43, "name": "Anoncoin", "symbol": "ANC", "website_slug": "anoncoin" }, { "id": 45, "name": "CasinoCoin", "symbol": "CSC", "website_slug": "casinocoin" }, { "id": 49, "name": "Bullion", "symbol": "CBX", "website_slug": "bullion" }, { "id": 50, "name": "Emerald Crypto", "symbol": "EMD", "website_slug": "emerald" }, { "id": 51, "name": "GlobalCoin", "symbol": "GLC", "website_slug": "globalcoin" }, { "id": 52, "name": "XRP", "symbol": "XRP", "website_slug": "ripple" }, { "id": 53, "name": "Quark", "symbol": "QRK", "website_slug": "quark" }, { "id": 56, "name": "Zetacoin", "symbol": "ZET", "website_slug": "zetacoin" }, { "id": 57, "name": "SecureCoin", "symbol": "SRC", "website_slug": "securecoin" }, { "id": 58, "name": "Sexcoin", "symbol": "SXC", "website_slug": "sexcoin" }, { "id": 61, "name": "TagCoin", "symbol": "TAG", "website_slug": "tagcoin" }, { "id": 63, "name": "I0Coin", "symbol": "I0C", "website_slug": "i0coin" }, { "id": 64, "name": "FlorinCoin", "symbol": "FLO", "website_slug": "florincoin" }, { "id": 66, "name": "Nxt", "symbol": "NXT", "website_slug": "nxt" }, { "id": 67, "name": "Unobtanium", "symbol": "UNO", "website_slug": "unobtanium" } ], "metadata": { "timestamp": 1532545712, "num_cryptocurrencies": 66, "error": null } }');
Realm, Inc.
- Danish startup founded in 2011
- Native object oriented database
- Used to be called TightDB
What is a Realm?
- A Realm is a lightweight object container
that acts like a database
- Data can be queried, filtered,
interconnected, persisted
- Live/Reactive objects
- Can contain multiple types with schema
enforcement
Benefits of a database built for mobile
Offline-First Functionality Make your app work as well offline as it does online. Fast Queries Even complex queries take nanoseconds, and stay up to date with new data. Safe Threading Access the same data concurrently from multiple threads, with no crashes. Cross-Platform Apps Use the same database for all your apps, on any major platform. Encryption Secure your data with transparent encryption and decryption. Reactive Architecture Connect your UI to Realm, and data changes will appear automatically.
Supported Platforms
Correlation
Realm Relational Database Realm Database /Connection Schema Table Object Row Object.Property Column
Re Realm St Studio
- Open and edit local
and synced Realms
- Administer any Realm
Object Server instance
- Available for Mac,
Windows, Linux
Supported Types (JavaScript)
Types Maps To bool JavaScript Boolean values int, float, double JavaScript number values
Internally int and double are stored as 64 bits while float is stored with 32 bits
string string data ArrayBuffer date Date
Query Language
- Inspired by NSPredicate
- Query Language:
https://realm.io/docs/javascript/latest/api/tutorial-query-language.html
- Cheat Sheet:
https://bit.ly/2nrwC7S
Fo Format String Su Summary
Ba Basic c Com Comparison
- ns
Ba Basic c Com Compou
- und
Pr Predicates
Str String Com Comparison
- n
Op Operators
Ag Aggregate Op Operators
Un Unsupported Op Operations
Un Unsupported Op Operations
Ti Tips s & Tricks
- Using OR OR OR instead of IN, results in repeatable code
and can be less efficient.
- When using REGEX and Matches, make sure they are the last
part of your predicate statement so it does less work.
- Write transactions have a non-negligible overhead; you
should try to minimize the number of write blocks within your code.
Define the Objects in Your Schema
const PersonSchema = { name: 'Person', primaryKey: 'id', properties: { id: 'int', // primary key firstName: 'string', lastName: 'string' } };
Define the Objects in Your Schema
const CryptocurrencySchema = { name: 'Cryptocurrency', primaryKey: 'symbol', properties: { name: { type: 'string', indexed: true }, symbol: 'string', price: 'double?', marketCap: {type: 'int', default: 0}, founder: 'Person' } };
Define the Objects in Your Schema
const ExchangeSchema = { name: 'Exchange', primaryKey: 'name', properties: { name: 'string', websiteUrl: 'string', coins: 'Cryptocurrency[]', } };
Realm.open({schema: [PersonSchema, ExchangeSchema, CryptocurrencySchema]}) .then(realm => { // Create Realm objects and write to local storage realm.write(() => { const bitcoin = realm.create('Cryptocurrency', { name: 'Bitcoin', symbol: 'BTC', price: 7500 }); bitcoin.price += 100; // Update a property value }); // Query Realm for all coins with a high price const coins = realm.objects('Cryptocurrency').filtered('price > 7500'); // Will return a Results object with our 1 coin coins.length; // => 1 // Add another coin realm.write(() => { const eth = realm.create('Cryptocurrency', { name: 'Ethereum', symbol: 'ETH’, price: 7503.24}); }); // Query results are updated in real-time coins.length // => 2 }) .catch(error => { console.log(error); });
Adding Objects
- Writes will block the thread they are made on.
- Reads are not blocked while a write is in progress.
try { realm.write(() => { realm.create('Cryptocurrency', {name: 'Dogecoin', symbol: 'DOGE'}); }); } catch (e) { console.log("Error on creation"); }
Updating Objects
- Writes will block the thread they are made on.
- You can update any object by setting its properties within a write transaction.
realm.write(() => { dogecoin.price = 482.11; }); realm.write(() => { // Create a coin object realm.create('Cryptocurrency', { id: 1, title: 'Primecoin', symbol: 'XPM', price: 541.32 }); // Update coin with new price keyed off the id realm.create('Cryptocurrency', {id: 1, price: 482.11}, true); });
Deleting Objects
- Objects can be deleted by calling the delete method within a write transaction.
realm.write(() => { // Create a coin object let coin = realm.create(‘Cryptocurrency’, { title: 'Potcoin', symbol: 'POT', price: 77.45 }); // Delete the coin realm.delete(coin); // Delete multiple coins by passing in a `Results`, `List`, // or JavaScript `Array` let allCoins = realm.objects('Cryptocurrency'); realm.delete(allCoins); // Deletes all coins });
To-One Relationships
For to-one relationships you specify the name property of the object schema you are referencing as the property’s type:
const CryptocurrencySchema = { name: 'Cryptocurrency', primaryKey: 'symbol', properties: { // The following property definitions are equivalent founder: {type: 'Person'}, founder: 'Person' } };
To-Many Relationships
const exchange = realm.objects('Exchange').filtered('name = "Coinbase "')[0]; let coins = createCoinObjects(); // <-- Not yet in Realm // exchange.coins = coins; // <-- Error coins = realm.copyToRealmOrUpdate(coins); exchange.coins = coins; // <-- OK
Inverse Relationships
- Links to other objects are unidirectional.
- With LinkingObjects properties, you can obtain all objects that link to a given object from a
specific property.
const PersonSchema = { name: 'Person', properties: { exchangesOwned: 'Exchange[]' } } const ExchangeSchema = { name: ‘Exchange', properties: { // No shorthand syntax for linkingObjects properties founder: {type: 'linkingObjects', objectType: 'Person', property: 'exchangesOwned'} } }
Migrations
Realm.open({ schema: [PersonSchema, ExchangeSchema, CryptocurrencySchema], schemaVersion: 1, migration: (oldRealm, newRealm) => { // only apply this change if upgrading to schemaVersion 1 if (oldRealm.schemaVersion < 1) { const oldObjects = oldRealm.objects('Person'); const newObjects = newRealm.objects('Person'); // loop through all objects and set name property in the new schema for (let i = 0; i < oldObjects.length; i++) { newObjects[i].name =
- ldObjects[i].firstName + ' ' + oldObjects[i].lastName;
} }}}).then(realm => { const fullName = realm.objects('Person')[0].name; });
Linear Migrations
const schemas = [ { schema: schema1, schemaVersion: 1, migration: migrationFunction1 }, { schema: schema2, schemaVersion: 2, migration: migrationFunction2 }, ... ] // the first schema to update to is the current schema version // since the first schema in our array is at let nextSchemaIndex = Realm.schemaVersion(Realm.defaultPath); while (nextSchemaIndex < schemas.length) { const migratedRealm = new Realm(schemas[nextSchemaIndex++]); migratedRealm.close(); } // open the Realm with the latest schema Realm.open(schemas[schemas.length-1]);
Notifications
- Realm Notifications: simple callbacks notified when write
transactions are committed
- Collection Notifications: more sophisticated callbacks which
receive change metadata on insertions, deletions and updates
- Describes what changes have occurred at a fine-grained level
- Consists of object indices that were inserted/deleted/modified since last
notification
Realm Notifications
function updateUI() { // ... } // Observe Realm Notifications realm.addListener('change', updateUI); // ..later remove the listener realm.removeListener('change', updateUI); // ..or unregister all listeners realm.removeAllListeners();
Encryption
var key = new Int8Array(64); // populate with a secure key Realm.open({ schema: [PersonSchema, ExchangeSchema, CryptocurrencySchema], encryptionKey: key }) .then(realm => { // Use the Realm as normal var coins = realm.objects('Cryptocurrency'); });
Limitations
- NSData and String properties limited to 16 MB in size
- No auto-incrementing properties
- No Built-in mechanism for obsolescence and data cleaning
Resources for Learning More
- Realm.io – official website and documentation
- https://academy.realm.io – Realm Academy
- https://caster.io/courses/realm - video tutorials
- https://proandroiddev.com/realistic-realm-1-5-year-of-experience-
cef75c8b164e
- github.com/realm
- StackOverflow – use the [realm] tag to filter search