Pipeline オペレーションを使用してデータを変更する

update(...) ステージと delete(...) ステージのデータ操作言語(DML)を使用して、ドキュメントをクエリしてからデータを削除または変更できるデータ パイプラインを構築します。

エディションの要件

このページで説明するオペレーションには、Firestore Enterprise エディションが必要です。

始める前に

Pipeline オペレーションを使用してデータベースをクエリする方法を理解している必要があります。

ドキュメントを更新する

update(...) DML ステージを使用して、ドキュメントをクエリし、データを追加または変更できるデータ パイプラインを構築します。

すべての DML ステージは、パイプラインの最後に配置する必要があります。このステージに移行するドキュメントには、更新するドキュメントを特定するための __name__ フィールドを含める必要があります。更新しようとしたドキュメントが存在しない場合、オペレーションは失敗します。

たとえば、次のオペレーションは、データモデルの変更をコレクション グループ内のすべてのドキュメントにバックフィルします。パイプラインは、users コレクション グループ内のすべてのドキュメントのうち、そのフィールドがないドキュメントすべてに preferences.color フィールドを追加します。

Node.js
const snapshot = await db.pipeline()
   .collectionGroup("users")
   .where(not(exists(field("preferences.color"))))
   .addFields(constant(null).as("preferences.color"))
   .removeFields("color")
   .update()
   .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Constant, Field, Not

snapshot = (
    client.pipeline()
    .collection_group("users")
    .where(Not(Field.of("preferences.color").exists()))
    .add_fields(Constant.of(None).as_("preferences.color"))
    .remove_fields("color")
    .update()
    .execute()
)
Java
Pipeline.Snapshot snapshot = firestore.pipeline()
   .collectionGroup("users")
   .where(not(exists(field("preferences.color"))))
   .addFields(constant((String) null).as("preferences.color"))
   .removeFields("color")
   .update()
   .execute().get();

ドキュメントを削除する

delete(...) ステージ DML ステージを使用して、ドキュメントをクエリしてデータを削除できるデータ パイプラインを構築します。一括削除の誤りを防ぐため、delete(...) で終わるパイプラインには、少なくとも 1 つの where(...) ステージを含める必要があります。すべての DML ステージはパイプラインの最後に配置する必要があります。

たとえば、次のパイプラインは、address.usersUSA に設定され、__create_time__ が 10 日未満のすべての users ドキュメントを削除します。

Node.js
const pipeline = db.pipeline()
  .collectionGroup("users")
  .where(field("address.country").equal("USA"))
  .where(field("__create_time__").timestampAdd("day", 10).lessThan(currentTimestamp()))
  .delete();
await pipeline.execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import CurrentTimestamp, Field

snapshot = (
    client.pipeline()
    .collection_group("users")
    .where(Field.of("address.country").equal("USA"))
    .where(
        Field.of("__create_time__")
        .timestamp_add("day", 10)
        .less_than(CurrentTimestamp())
    )
    .delete()
    .execute()
)
Java
Pipeline.Snapshot deleteResults = firestore.pipeline()
  .collectionGroup("users")
  .where(field("address.country").equal("USA"))
  .where(field("__create_time__").add(constant(10)).lessThan(currentTimestamp()))
  .delete()
  .execute().get();

整合性

update(...) ステージと delete() ステージを含むパイプライン オペレーションは、トランザクション内ではサポートされていません。DML ステージは、次の動作でトランザクションの外部で実行されます。

  • 各ドキュメントは個別に更新されます。つまり、オペレーションはドキュメント間でアトミックではありません。操作は最初のエラーで失敗し、部分的な成功は可能です。
  • 次のステージがサポートされています。
    • collection(...)
    • collection_group(...)
    • where(...)
    • select(...)
    • add_fields(...)
    • remove_fields(...)
    • let(...)
    • sort(...)
    • limit(...)
    • offset(...)
  • 次のステージはサポートされていません。
    • aggregate(...)
    • distinct(...)
    • unnest(...)
    • find_nearest(...)
    • union(...)、結合、サブクエリなどのマルチクエリ ステージは、DML ステージの前に使用できません。

制限事項

DML ステージには次の制限事項があります。

  • DML ステージは、.execute() を呼び出す前のパイプライン定義の最後のステージである必要があります。
  • update(...) ステージと delete() ステージを含むパイプライン オペレーションは、トランザクション内ではサポートされていません。
  • DML ステージの前のステージで同じ __name__ を持つ複数のドキュメントが生成された場合、各インスタンスが処理されます。update(...) の場合、同じターゲット ドキュメントが複数回変更される可能性があります。delete(...) の場合、最初の試行後の後続の試行は no-op になります。