Azure の Cosmos DB を使っていて非常に困るのが、コレクションのパーティションキー設計を変更したい場合になった時です。パーティションキーは作成時にしか設定できず、後から変えることは不可能です。
設計ミスと言われると何とも言い返せないのですが、こういうのは使ってから発覚するものなのです。一応ある程度までは RU を監視して、クエリを最適化することで改善は行えました。
しかし、大体はクロスパーティションなクエリのせいで問題が発生するので、必要ない場合はパーティションキーを使わないという選択肢を取った方が良いことが多いように思います。
なので、新しくコレクションを作成してデータを全て移行すれば一応は解決するのですが、Cosmos DB にはコレクションのコピーといった機能は用意されておらず、パーティションキーと RU が関わってくるので自分で用意するのは現実的ではないように思います。
そこで Azure Data Factory を使います。コピーアクティビティを使ってコピー元に古いコレクションを、コピー先に新しいコレクションの指定出来るので簡単にコピーが可能でした。
ドキュメントには Cosmos DB => Cosmos DB に関しては書かれていないですが、特に設定さえ行えば問題ないようです。RU に関してもリトライを適切に行ってくれるみたいです。
とりあえず実際に Cosmos DB のコレクションコピーを行ってみます。パーティションキーを設定しているコレクションから設定していないコレクションへのコピーです。データは適当に用意しました。
パーティションキーは GUID にしたので、クロスパーティションクエリを使わない限り、このデータは取り出せません。このデータをそのまま新しいコレクションにコピーするのが目的です。
次に Data Factory を Cosmos DB と出来れば同じリージョンに作成して、専用のポータルにアクセスします。Copy Data という非常に分かりやすいボタンがあるのでクリックして設定を進めていきます。
ウィザード形式でパイプラインの作成が進んでいくので、良い感じに設定していきます。
コピータスクは基本的には 1 回しか実行しないので "Run once now" を選択しておきます。
次はコピー元のデータストアを選びます。Cosmos DB の接続を新しく追加するだけです。
接続を作成すれば、Cosmos DB の情報が表示されるようになるので、そこでコピー元になるコレクションを選択します。データはプレビューされるので便利です。
データの変換が必要な場合は、ここでスキーマやクエリを変更することも出来るみたいですが、今回は全データのコピーなので下の方にあるチェックを入れました。これを有効にするとそのままの JSON としてデータをエクスポートしてくれます。
次はコピー先の設定です。同じように Cosmos DB の接続を選ぶと、どのコレクションにコピーするか選べるようになります。この辺りは単純なので迷うことはなさそうです。
これで設定完了なので、後はボタンをポチポチ押していくと、パイプラインのデプロイと実行が行われます。1000 ドキュメントのコピーでしたが、一瞬で完了しました。
新しいコレクションのデータを確認すると、ちゃんとそのままの形でコピーされています。
Cosmos DB が管理用に作成するデータは変わっているので、タイムスタンプなどは失われています。
パーティションキーに使っていたデータなどはそのままの状態で、コレクション側のパーティションキーが無くなっているだけなので、非常に扱いやすいデータになりました。
例えばカラムを typo していたとか、構造を少し変えたいといった場合にも Data Factory のコピーが使える気がします。スキーマレスといってもデータが既にある場合には構造を変えるのは難しいものです。