Realm-js中更新用户时重复创建城市记录的原因排查
问题原因分析
你遇到的重复创建Cities记录的问题,核心原因在于你往用户的city列表里推送的是普通JavaScript对象,而非Realm中已存在的Cities实例。
Realm的List类型在处理添加操作时,会自动把传入的普通JS对象转化为对应模型的Realm对象并持久化——哪怕你以为这个城市已经存在,只要传的不是从Realm查询出来的实例,它就会当作新记录插入Cities表,完全不会检查属性是否重复。
解决方案
方案1:先查询已有城市,再添加实例
在推送城市到用户列表前,先查询Cities表中是否存在匹配记录。如果存在就用查询到的Realm实例,不存在再创建新实例:
addCity = (cityObj) => { realm.write(() => { // 查询是否存在匹配的城市 let existingCity = realm.objects('Cities').filtered('name = $0 AND pincode = $1', cityObj.name, cityObj.pincode)[0]; let targetCity; if (!existingCity) { // 不存在则创建新记录 targetCity = realm.create('Cities', cityObj); } else { // 存在则复用已有实例 targetCity = existingCity; } let user = realm.create('Users', { 'id': 'someUniqueID' }, true); // 推送Realm实例而非普通JS对象 user.city.push(targetCity); }); let cities = realm.objects('Cities'); console.log('cities.length', cities.length); }
方案2:给Cities模型添加唯一键(推荐)
如果想从根源避免Cities表出现重复记录,可以给Cities的schema添加primaryKey(比如用name和pincode生成组合唯一键):
修改Cities的schema:
Cities.schema = { name: 'Cities', primaryKey: 'uniqueKey', // 添加主键 properties: { 'name': { type: 'string' }, 'pincode': { type: 'int' }, 'uniqueKey': { type: 'string', computed: '{name}_{pincode}' } // 用计算属性生成唯一标识 } };
之后创建城市时,Realm会自动根据主键判断是否存在,不存在则创建,存在则更新:
addCity = (cityObj) => { realm.write(() => { // 创建或获取已存在的城市实例 let targetCity = realm.create('Cities', { ...cityObj, uniqueKey: `${cityObj.name}_${cityObj.pincode}` }, true); // 第三个参数true表示"更新或创建" let user = realm.create('Users', { 'id': 'someUniqueID' }, true); user.city.push(targetCity); }); let cities = realm.objects('Cities'); console.log('cities.length', cities.length); }
这样无论调用多少次addCity,只要城市的name和pincode相同,Cities表中只会保留一条记录,不会重复创建。
内容的提问来源于stack exchange,提问作者Anshul Masne
相关产品推荐
相关产品推荐

