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

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

エディションの要件

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

始める前に

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

ドキュメントを更新する

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

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

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

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 ステージは、パイプラインの最後に配置する必要があります。

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

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() ステージの Pipeline オペレーションは、トランザクション内ではサポートされていません。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() ステージの Pipeline オペレーションは、トランザクション内ではサポートされていません。
  • DML ステージの前のステージで同じ __name__ のドキュメントが複数生成された場合、各インスタンスが処理されます。update(...) の場合、同じターゲット ドキュメントが複数回変更される可能性があります。delete(...) の場合、最初の試行後の試行は no-op になります。