2017-06-27 97 views
0

我正在使用realm-js來爲用戶在其設備上使用React Native存儲數據,並且在工作流程中存在一點,我希望將該數據中的所有數據當地領域進入同步領域(堅持ROS)。我遇到了一個問題,在我們的模式中,我們通過將引用一個對象的屬性添加到另一個對象中創建了僞關係,反之亦然,並且我們創建了循環數據結構。realm-js - 將本地領域數據複製到sycned領域

這實際上在應用程序中工作正常,但現在我們試圖將數據從本地領域複製到同步的領域,並且由於循環引用的原因,它似乎崩潰了。

例如,模式看起來像這樣。

class Person extends Realm.Object {} 
Person.schema = { 
    name: 'Person', 
    properties: { 
    firstName: { 
     type: 'string', 
     optional: true, 
    }, 
    staffAccount: { 
     type: 'StaffAccount' 
    }, 
    }, 
}; 

class StaffAccount extends Realm.Object {} 
StaffAccount.schema = { 
    name: 'StaffAccount', 
    properties: { 
    id: { 
     type: 'string', 
    }, 
    people: { 
     type: 'list', 
     objectType: 'Person', 
    }, 
    }, 
}; 

在這個例子中創建一個人,你會定義一個staffAccount財產和人員帳戶屬性時,必須具有與該員工的帳戶,並在該列表中會有人的人列表的人財物Person模式中的初始人員。

在將數據從一個域複製到另一個域時,有什麼辦法可以解決這個問題嗎?

回答

1

看看這個代碼需要一個本地.realm文件並將其複製到遠程同步的Realm中。代碼可以簡化,因爲它看起來像你已經知道架構 - 這些代碼動態加載架構。希望它有幫助

// Copy local realm to ROS 

const Realm = require('realm'); 


// UPDATE THESE 
const realm_server = 'localhost:9080'; 

const source_realm_path = './localRealm.realm'; // path on disk 
const target_realm_path = '/syncRealm'; // path on server 


function copyObject(obj, objSchema, targetRealm) { 
    const copy = {}; 
    for (var key in objSchema.properties) { 
     const prop = objSchema.properties[key]; 
     if (prop.type == 'list') { 
      const propObjSchema = targetRealm.schema.find((s) => s.name == prop.objectType) 
      copy[key] = obj[key].map((obj) => copyObject(obj, propObjSchema, targetRealm)) 
     } 
     else if (prop.type == 'object') { 
      const propObjSchema = targetRealm.schema.find((s) => s.name == prop.objectType) 
      copy[key] = obj[key] ? copyObject(obj[key], propObjSchema, targetRealm) : obj[key]; 
     } 
     else { 
      copy[key] = obj[key]; 
     } 
    } 
    return copy; 
} 

function getMatchingObjectInOtherRealm(sourceObj, source_realm, target_realm, class_name) { 
    const allObjects = source_realm.objects(class_name); 
    const ndx = allObjects.indexOf(sourceObj); 

    // Get object on same position in target realm 
    return target_realm.objects(class_name)[ndx]; 
} 

function addLinksToObject(sourceObj, targetObj, objSchema, source_realm, target_realm) { 
    for (var key in objSchema.properties) { 
     const prop = objSchema.properties[key]; 
     if (prop.hasOwnProperty('objectType')) { 
      if (prop['type'] == "list") { 
       var targetList = targetObj[key]; 
       sourceObj[key].forEach((linkedObj) => { 
        const obj = getMatchingObjectInOtherRealm(linkedObj, source_realm, target_realm, prop.objectType); 
        targetList.push(obj); 
       }); 
      } 
      else { 
       // Find the position of the linked object 
       const linkedObj = sourceObj[key]; 
       if (linkedObj === null) { 
        continue; 
       } 

       // Set link to object on same position in target realm 
       targetObj[key] = getMatchingObjectInOtherRealm(linkedObj, source_realm, target_realm, prop.objectType); 
      } 
     } 
    } 
} 

function copyRealm(user, local_realm_path, remote_realm_url) { 
    // Open the local realm 
    const source_realm = new Realm({path: local_realm_path}); 

    // Create the new realm (with same schema as the source) 
    const target_realm = new Realm({ 
     sync: { 
      user: user, 
      url: remote_realm_url, 
     }, 
     schema: require('./realmmodels') 
    }); 

    // Copy all objects but ignore links for now 
    target_realm.schema.forEach((objSchema) => { 
     console.log("copying objects:", objSchema['name']); 
     const allObjects = source_realm.objects(objSchema['name']); 
     target_realm.write(() => 
      allObjects.forEach((obj) => { 
       // Add this object to the target realm 
        target_realm.create(objSchema.name, copyObject(obj, objSchema, target_realm), true) 
     })); 
    }); 
} 

const remote_realm_url = "realm://" + realm_server + target_realm_path; 
copyRealm(Realm.Sync.User.adminUser("ADMIN_TOKEN"), 
    source_realm_path, remote_realm_url); 
console.log("done");