9

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

我的第一个想法是在迁移中重命名模式并手动复制数据,但随后 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 注释并进行迁移时,领域显然会抱怨重复值。我需要在不破坏其他模型中的链接的情况下删除这些重复项。

4

2 回答 2

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) {
            ...
        }
    }
}

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

于 2016-08-26T09:50:56.240 回答
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);

编辑:
我在基础上进行了编辑。这些是应该解决这个问题的以下步骤:
1. 创建新字段,不要将其标记为主键。
2. 使用变换将新字段设置为每个实例的唯一值
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);
于 2016-08-26T08:56:10.103 回答