将PrimaryKey添加到具有大量重复数据的Realm

时间:2016-08-26 08:38:20

标签: java android realm database-migration realm-migration

我需要在两个由于白痴而错过它的Realm模型中添加@PrimaryKey。这些模型通过直接关系或RealmLists在多个其他模型中引用,其中一个模型也引用了另一个模型。

我的第一个想法是在迁移中重命名模式并手动复制数据,但是Realm抱怨模式在其他模式中链接,并且无法重命名。

这两个模式包含大约15000个可以压缩到大约100个的对象,它们完全相同,并且由于缺少@PrimaryKey而被复制。

模特本身有点简单:

class ModelA extends RealmObject {
     String primaryKey; // Is missing the @PrimaryKey annotation
     String someField;
     String someOtherField;
     Date someDate;
     ModelB relationToTheOtherProblematicModel;
}

class ModelB extends RealmObject {
    String primaryKey; // Is also missing the @PrimaryKey annotation
    // this class only contains String fields and one Date field
}

当我向这两个类添加@PrimaryKey时,如何迁移数据' primaryKey字段?

编辑以澄清:

两个模式都包含多个完全相同的项目。

primaryKey | someField | someOtherField
------     | ------    | ------
A          | foo       | bar
A          | foo       | bar
A          | foo       | bar
A          | foo       | bar
B          | bar       | foo
B          | bar       | foo
B          | bar       | foo
C          | far       | boo
C          | far       | boo
C          | far       | boo

可以删除这些重复项,因为primaryKey唯一标识它们。当我添加@PrimaryKey注释并进行迁移时,Realm显然会抱怨重复的值。我需要删除那些重复项而不破坏其他模型中的链接。

2 个答案:

答案 0 :(得分:0)

你有没有试过这样的事情:

RealmConfiguration config = new RealmConfiguration.Builder(this)
            .schemaVersion(6) //the new schema version
            .migration(new RealmMigration() {
                @Override
                public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {

                    RealmSchema schema = realm.getSchema();
                    schema.get("ClassA").addPrimaryKey("primaryKey");
                    schema.get("ClassB").addPrimaryKey("primaryKey");
                }
            })
            .build();
Realm.setDefaultConfiguration(config);

修改
我根据this进行了编辑。以下是应解决此问题的步骤:
1.创建新字段,不要将其标记为主键 2.使用transform
将新字段设置为每个实例的唯一值 3.在新字段中添加索引 4.将新字段设为主键。

RealmConfiguration config = new RealmConfiguration.Builder(this)
            .schemaVersion(6) //the new schema version
            .migration(new RealmMigration() {
                @Override
                public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {

                    RealmSchema schema = realm.getSchema();
                    schema.get("ClassA").addField("newKey", String.class)
                        .transform(new RealmObjectSchema.Function() {
                            @Override
                            public void apply(DynamicRealmObject obj) {
                                obj.set("newKey", obj.getString("primaryKey"));
                            }
                        })
                        .addIndex("newKey")
                        .addPrimaryKey("newKey");

                    schema.get("ClassB").addField("newKey", String.class)
                        .transform(new RealmObjectSchema.Function() {
                            @Override
                            public void apply(DynamicRealmObject obj) {
                                obj.set("newKey", obj.getString("primaryKey"));
                            }
                        })
                        .addIndex("newKey")
                        .addPrimaryKey("newKey");
                }
            })
            .build();
        Realm.setDefaultConfiguration(config);

答案 1 :(得分:0)

您是否尝试在迁移前删除重复的对象?例如,在您的迁移类中,您可以执行类似......

的操作
RealmMigration migration = new RealmMigration() {
    @Override
    public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {

        RealmResults<ModelA> modelAs = realm.where(ModelA.class)
                                            .equals("primaryKey", "whatever")
                                            .findAll();

        for (int i = 1; i < modelAs.size(); i++) {
            modelAs.get(i).deleteFromRealm();
        }

        // Migration code...
        if (oldVersion == 1) {
            ...
        }
    }
}

然后,每个primaryKey只有1个元素,因此可以执行迁移。