在迁移过程中,如何删除未被其他对象引用的Realm对象?

时间:2019-03-18 12:25:30

标签: android realm realm-java

我有两个模型-

class Direction : RealmObject {
    var distance : Int
    var polyline : String
}

class Route  : RealmObject {
    var id : String
    var directionList : RealmList<Direction>
}

我一直在使用insertOrUpdate()来更新Route类,并假设当我调用它时,directionList中现有的方向对象已删除,并由我提供的新列表替换。但是,我最近发现这没有发生。当我调用route.deleteFromRealm()时,甚至不支持级联删除。因此,现在我最终在Directions表中获得了数百个对象,而没有对象引用它们。

如何从Direction类中删除所有在Realm迁移中没有引用到它们的Route对象的对象?

3 个答案:

答案 0 :(得分:1)

我可以想到两种可能的方式。

第一人目前可能无法为您提供帮助,但将来可能会有所帮助。通过将LinkingObjects属性添加到Direction类,可以让模型确定哪些Direction对象没有相关的Route对象。此处描述了LinkingObjects(https://realm.io/docs/java/5.8.0/api/io/realm/annotations/LinkingObjects.html)。在Direction上有一个属性:例如:

\@LinkingObjects("direction")
final RealmResults<Route> routes = null;

然后,您可以删除以下任何对象:

RealmResults<Direction> unusedDirections = realm.where(Direction.class).isEmpty("routes").findAll();

尽管如此,您可能需要在下一个版本中执行此操作。

第二种方法缠绕的时间更长,但本质上是:

  1. 找到所有Direction个对象:RealmResults<Direction> redundantDirections = realm.where(Direction.class).findAll();
  2. 找到所有Route个对象(类似于上面的对象)。
  3. 遍历所有Route对象。
  4. 过滤redundantDirections查询以排除每个Direction对象引用的所有Route对象。
  5. 删除最后一个redundantDirections

我希望有第三种我不知道的方式.....

答案 1 :(得分:1)

这是我解决问题的方法-

override fun migrate(realm: DynamicRealm, oldVersion1: Long, newVersion: Long) {

    if (oldVersion == 2L) {

        val routeSchema = schema.get("Route")
        val directionSchema = schema.get("Direction")

        /*
        Creating a new temp field called isLinked which is set to true for those which are
        references by Route objects. Rest of them are set to false. Then removing all
        those which are false and hence duplicate and unnecessary. Then removing the temp field
        isLinked
         */
        directionSchema!!
                .addField("isLinked", Boolean::class.java)
                .transform { obj ->
                    //Setting to false for all by default
                    obj.set("isLinked", false)
                }

        routeSchema!!.transform { obj ->
            obj.getList("directionList").forEach {
                //Setting to true for those which are referenced
                it.set("isLinked", true)
            }
        }

        //Removing all those which are set as false
        realm.where("Direction")
                .equalTo("isLinked", false)
                .findAll()?.deleteAllFromRealm()

        directionSchema.removeField("isLinked")

        //Rest of the migration
    }
}

我发现了更多东西。根据关于领域-https://academy.realm.io/posts/jp-simard-realm-core-database-engine/(跳至28:45)的非常有用的演讲,有一种方法可以从B树中删除所有那些未引用的节点。但是,我找不到办法。 Realm.compactRealm()似乎是一种方法,但是没有用。

答案 2 :(得分:0)

  

在Realm迁移中,如何从Direction类中删除所有没有Route对象引用的对象?

使用DynamicRealmObject.linkingObjects应该很容易。

val routes = realm.where("Destination").findAll()
routes.createSnapshot().forEach { route ->
    val linkingObjects = route.linkingObjects("Route", "directionList")
    if(linkingObjects.isEmpty()) {
        route.deleteFromRealm()
    }
}

从理论上讲这应该起作用