在RN中使用realm數據庫

在移動開發領域,realm是最熱門的跨平臺數據庫,沒有之一。而現在,realm已經把他的觸手伸到了服務端,在node.js服務器上也可以運行realm了(可以認爲是mongodb的競爭對手了)。但我們這裏所討論的realm仍然侷限於realm的本地數據庫,也就是它一開始被設計用來做的事:在ios上的競爭對手是fmdb/coredata, 安卓上的greendao等。

realm的js文檔非常完備和友好,推薦大家閱讀,我這裏會簡單介紹一下它主要的功能和使用。

https://realm.io/docs/javascript/latest/

1. schema. schema是realm的模型,也就是說它定義了model的格式;在rn上我們可以通過json和es 6的class兩種方式來對它進行定義; 這裏的name唯一代表了一個model的類型,如果需要升級之則需要給realmdb指定版本號:schemaVersion; 值得一提的是realm的模型升級機制非常完備,並且考慮了多版本升級的數據遷移問題,可謂是非常貼心了。model的所有字段都支持默認值設置,例:

 miles: {type: 'int',    default: 0}

2. realm支持的數據類型有:bool, string, date, int ,float, double ,data(數組); 作爲一個orm的數據庫,當然它也可以將realm的對象嵌套在model中存儲。此時我們在model裏面給字段指定類型的時候就要輸入嵌套對象的name。realm也支持將對象放在數組中作爲屬性,比如一個person可以擁有一個dogs的字段,這裏存放的是dog類型的對象數組。這是一種單向的鏈接關係(dog存放在dog表中,person則擁有他的dogs),我們還可以在dog裏面指定反向的鏈接關係,代碼示例如下:

const PersonSchema = {
  name: 'Person',
  properties: {
    dogs: 'Dog[]'
  }
}

const DogSchema = {
  name:'Dog',
  properties: {
    // No shorthand syntax for linkingObjects properties
    owners: {type: 'linkingObjects', objectType: 'Person', property: 'dogs'}
  }
}
這裏的狗可能是屬於某個家庭,一個人也可能擁有多隻狗,所以這裏的狗和人存在正向和反向的鏈接關係。

3. 字段可以設置爲索引值(付出的代價是插入變慢,收穫是查詢和搜索速度變快),且一個model可以設置一個主鍵值(類型可以是string或者int),可以通過主鍵直接訪問對象。

4. 關於操作:增刪改相關的操作一般來說需要放在write block中(transaction),代碼編寫起來也是比較方便的。realm支持對象的排序、過濾搜索等,還支持簡單的語句(類似於iOS中的NSPredicate)。值得一提的是realm的值都是lazy load的,所以對於大數據集的訪問可以直接獲取,而不用擔心內存溢出之類的問題,使用的時候先排序再通過slice獲取即可。 也是基於性能的考慮,realm獲取到的值的順序並不能保證和插入的順序一致,所以在開發時需要通過你自己的機制來保證順序(比如key或者基於值的排序等等)。

5. 同步訪問: realm db除了通過異步方式打開以外,也支持同步打開db進行操作(但不推薦,因爲同步方式會帶來可能的數據不一致等問題,還有可能有性能方面的問題),代碼如下:

const realm = new Realm({schema: [PersonSchema]});

// You can now access the realm instance.
realm.write(/* ... */);
6. 數據庫變更的通知

通知機制讓我們可以以一種優雅的方式在多處操作數據庫並刷新UI。對於本地數據庫,realm提供了兩個維度的通知:

a. 數據庫變更通知

function updateUI() {
  // ...
}

// Observe Realm Notifications
realm.addListener('change', updateUI);
這是一種很粗的listener,當write transaction發生時,就會觸發這個事件。所有的增、刪、改操作都應該在write transaction內部發生,也就是說會引發數據庫的變更。我們可以在這裏做一個簡單的reload.

b. 數據集變更通知

該通知是綁定在realm對象/對象集合上的。回調的參數也有兩個:1.觀察的數據集本身 2.變更

示例代碼如下:

// Observe Collection Notifications
realm.objects('Dog').filtered('age < 2').addListener((puppies, changes) => {

  // Update UI in response to inserted objects
  changes.insertions.forEach((index) => {
    let insertedDog = puppies[index];
    ...
  });

  // Update UI in response to modified objects
  changes.modifications.forEach((index) => {
    let modifiedDog = puppies[index];
    ...
  });

  // Update UI in response to deleted objects
  changes.deletions.forEach((index) => {
    // Deleted objects cannot be accessed directly
    // Support for accessing deleted objects coming soon...
    ...
  });

});

// Unregister all listeners
realm.removeAllListeners();
此外,realm也支持同時存在多個db以及配置不同的本地存儲路徑、支持64位的aes加密、支持inmemory模式等等,作爲一個移動db領域的巨頭玩家,我認爲realm可以作爲react native開發中本地數據庫的第一選擇。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章