使用管道作業修改資料

使用 update(...)delete(...) 資料操縱語言 (DML) 階段,建構可查詢文件,然後刪除或修改資料的資料管道。

版本需求

本頁所述作業需要使用 Firestore Enterprise 版。

事前準備

您應熟悉如何透過管道作業查詢資料庫

更新文件

使用 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(...) 結尾的管道應至少包含一個 where(...) 階段。所有 DML 階段都必須位於管道結尾。

舉例來說,下列管道會刪除所有 users 文件,這些文件將 address.users 設為 USA,且 __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() 階段的管道作業。DML 階段會在交易外執行,且具有下列行為:

  • 每份文件都會獨立更新。也就是說,作業不會以原子方式跨文件執行。作業會在發生第一個錯誤時失敗,但可能部分成功。
  • 支援的階段如下:
    • collection(...)
    • collection_group(...)
    • where(...)
    • select(...)
    • add_fields(...)
    • remove_fields(...)
    • let(...)
    • sort(...)
    • limit(...)
    • offset(...)
  • 不支援下列階段:
    • aggregate(...)
    • distinct(...)
    • unnest(...)
    • find_nearest(...)
    • DML 階段之前不得有多重查詢階段,例如 union(...)、聯結和子查詢。

限制

請注意,DML 階段有下列限制:

  • 在呼叫 .execute() 之前,DML 階段必須是管道定義中的最後階段。
  • 交易中不支援使用 update(...)delete() 階段的管道作業。
  • 如果 DML 階段之前的階段產生多個具有相同 __name__ 的文件,系統會處理每個執行個體。對於 update(...),這表示同一個目標文件可能會多次修改。如果是 delete(...),第一次嘗試後續的嘗試都會是無運算。