schemaversionテクニックを利用したスキーマ変更を試す

App EngineのDatastoreにおけるスキーマ変更に対応するために、schemaVersionというテクニックが編み出されています。Slim3本ではChapter7-4-1(p.265)で紹介されています。
自分の場合には、以下のようなケースでスキーマ変更が必要になりました。

日付のプロパティを持たせて、並べ替えたくなった

エンティティの取得結果を、日付の新しい順に表示したくなりました。しかし、既存のエンティティには日付の情報を持たせてません。そこで、Modelの定義を変更して、Date型のプロパティを追加することにしました。

	private Date date;
	public Date getDate() {
		return date;
	}
	public void setDate(Date date) {
		this.date = date;
	}

取得する処理も、日付の新しい順=descで並べ替えるようにします。

		List<Slim3Model> models = Datastore.query(meta).asList();

↓ sortを追加

		List<Slim3Model> models = Datastore.query(meta).sort(meta.date.desc).asList();

これで、取得結果は新しい日付順に。。。と思いきや、このままだと以前のエンティティが取得されなくなってしまいます。
要は以前のエンティティはdateプロパティそのものがない(=missing)なので、ソート結果の取得に必要なシングルプロパティインデックスが存在しないからです。これについてはSlim3本のChapter4-4(p.40)に詳しい説明があります。本んの説明にあるとおり、missingのエンティティだけを抽出する、ということはできません。
そこでmissingを抽出するフィルタ条件の代わりとして、schemaVersionというプロパティを持たせとこう、というテクニックです。上記でdateプロパティを追加したら、schemaVersionをインクリメントします。schemaVersionはアノテーションで管理されています。

@Model(schemaVersion=2)
public class Slim3Model {
    // 略
}

スキーマバージョンによるエンティティの抽出

特定のスキーマバージョンを抽出するには下記のようなコードで抽出できました。

Long targetSchemaVersion = new Long(1);
		List<Slim3Model> models = Datastore.query(meta).filter(meta.getSchemaVersionName(), FilterOperator.EQUAL, targetSchemaVersion).asList();

取得結果を再度putすれば、スキーマバージョンは最新のものにかきかわり、missingだったdateプロパティはnullになります。
nullだろうがなんだろうが、プロパティがありさえすればシングルプロパティインデックスが作成されるので、dateでソートしたクエリの結果にも以前のエンティティが含まれるようになります。

以前のエンティティが大量にある場合

古いスキーマバージョンのエンティティが大量にある場合はputするにも30秒制限にひっかかるので、TaskQueueで小分けにしてputする、というようなことが必要になるみたいです。(すみません、このへん曖昧です)