如何在Realm数据库中避免列重复条目并获取唯一值?
嘿,这个问题太实用了!我分两部分给你捋清楚——先解决怎么从根源避免重复条目,再教你怎么做去重查询拿到你要的唯一值。
这里有两种靠谱的方案,看你的需求选:
用主键约束从根源杜绝重复
Realm支持给模型字段设置主键,只要标记了主键,当你插入相同主键值的条目时,Realm会自动处理(要么覆盖旧数据,要么抛出异常,看你用的方法)。比如你的数据是数值类型,模型类可以这么定义(以Kotlin为例):open class NumberModel( @PrimaryKey open var value: Int = 0 ) : RealmObject()插入数据时用
copyToRealmOrUpdate()方法,这样如果已经存在相同value的条目,就会更新旧数据,不会新增重复:realm.executeTransaction { realm -> val number = NumberModel(4) realm.copyToRealmOrUpdate(number) }如果你想禁止覆盖,只允许插入全新的条目,可以用
copyToRealm(),它会在主键重复时抛出RealmPrimaryKeyConstraintException,你可以捕获这个异常提示用户“该值已存在”。手动检查后再插入
要是你需要的是多字段组合唯一(比如同时判断value和type不能重复),没法用单个主键,那就在插入前先查一遍数据库:realm.executeTransaction { realm -> // 组合条件查询是否存在重复 val existing = realm.where(NumberModel::class.java) .equalTo("value", 4) .equalTo("type", "count") .findFirst() if (existing == null) { realm.copyToRealm(NumberModel(4, "count")) } }
针对你给出的例子,要从一堆重复值里拿到2、3、4、5、6这几个唯一值,用Realm的distinct()方法最方便:
直接用
distinct()做数据库层面去重
这个方法是在数据库端处理的,性能比加载所有数据到内存再去重好太多。代码示例:// 查询value字段的唯一值 val uniqueValues = realm.where(NumberModel::class.java) .distinct("value") .findAll() .map { it.value }如果你需要排序后的结果,再加个
sort()就可以:val sortedUniqueValues = realm.where(NumberModel::class.java) .distinct("value") .sort("value") // 按value升序排序 .findAll() .map { it.value }这样得到的就是
[2,3,4,5,6]啦。旧版本Realm的手动去重方案
要是你的Realm版本比较老(现在很少见了)不支持distinct(),可以先查询所有数据,再用集合去重:val allValues = realm.where(NumberModel::class.java).findAll().map { it.value } val uniqueValues = allValues.distinct()不过这种方法在数据量大的时候会占用较多内存,优先推荐用
distinct()。
另外补充一句:如果需要多字段组合去重,比如要value和type同时唯一的对象列表,也可以传字段数组给distinct():distinct(arrayOf("value", "type"))。
内容的提问来源于stack exchange,提问作者Prajakta

