ใช้ขั้นตอนภาษาในการจัดการข้อมูล (DML) update(...) และ delete(...) เพื่อสร้าง Data Pipeline ที่สามารถค้นหาเอกสาร แล้วลบหรือแก้ไขข้อมูล
ข้อกำหนดของรุ่น
การดำเนินการที่อธิบายไว้ในหน้านี้ต้องใช้ Firestore Enterprise Edition
ก่อนเริ่มต้น
คุณควรคุ้นเคยกับวิธีค้นหาฐานข้อมูลด้วยการดำเนินการไปป์ไลน์
อัปเดตเอกสาร
ใช้ระยะ DML update(...) เพื่อสร้าง Data Pipeline ที่สามารถค้นหาเอกสาร แล้วเพิ่มหรือแก้ไขข้อมูล
ระยะ 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();
Go
snapshot := client.Pipeline(). CollectionGroup("users"). Where(firestore.Not(firestore.FieldExists(firestore.FieldOf("preferences.color")))). AddFields(firestore.Selectables( firestore.ConstantOfNull().As("preferences.color"), )). RemoveFields(firestore.Fields("color")). Update(). Execute(ctx)
ลบเอกสาร
ใช้ระยะ DML delete(...) เพื่อสร้าง Data Pipeline ที่สามารถค้นหาเอกสารแล้วลบข้อมูล
เพื่อป้องกันการลบข้อมูลจำนวนมากโดยไม่ตั้งใจ ไปป์ไลน์ที่ลงท้ายด้วย delete(...) ควรมีระยะ where(...) อย่างน้อย 1 ระยะ
ระยะ 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();
Go
snapshot := client.Pipeline(). CollectionGroup("users"). Where(firestore.FieldOf("address.country").Equal("USA")). Where(firestore.FieldOf("__create_time__").Add(firestore.ConstantOf(10)).LessThan(firestore.CurrentTimestamp())). Delete(). Execute(ctx)
โหมดการดำเนินการและความสอดคล้อง
คุณสามารถเรียกใช้ขั้นตอน DML ได้ทั้งภายในธุรกรรมที่ชัดเจนหรือภายนอกธุรกรรม ดังนี้
การดำเนินการธุรกรรม
DML แบบธุรกรรมให้ความสอดคล้องแบบอะตอมมิก (ทั้งหมดหรือไม่มีเลย) ในเอกสารต่างๆ และรองรับขั้นตอนการค้นหาไปป์ไลน์ทั้งชุด ซึ่งเหมาะสำหรับภาระงานที่ต้องการการรับประกันความสอดคล้องที่เข้มงวด โดยที่การอัปเดตบางส่วนเป็นสิ่งที่ยอมรับไม่ได้ หรือภาระงานที่อาศัยขั้นตอนการค้นหาที่ซับซ้อน โดยที่การแก้ไขต้องอยู่ภายในขีดจำกัดขนาดธุรกรรม
การเรียกใช้ไปป์ไลน์ DML ภายในธุรกรรมที่ชัดเจน (โดยใช้ runTransaction / transaction.execute(pipeline) หรือตัวเลือก atomic: true) จะมีลักษณะการทำงานต่อไปนี้
- การเปลี่ยนแปลงทั้งหมดจะคอมมิตพร้อมกันหรือย้อนกลับทั้งหมดเมื่อดำเนินการไม่สำเร็จ
- ระบบรองรับขั้นตอนการค้นหาไปป์ไลน์ทั้งหมดก่อนขั้นตอน DML (รวมถึงการค้นหาย่อย
where,add_fields,union,find_nearestและaggregate) - ในธุรกรรม การดำเนินการอ่านทั้งหมดต้องดำเนินการก่อนการดำเนินการเขียนใดๆ เนื่องจากไปป์ไลน์ DML ทำการเขียน คุณจึงไม่สามารถดำเนินการอ่านหลังจากเรียกใช้ไปป์ไลน์ DML ในธุรกรรมเดียวกันได้ เช่น คุณไม่สามารถเรียกใช้ไปป์ไลน์ DML หลายครั้งในธุรกรรมเดียว และไม่สามารถอ่านเอกสารหลังจากเรียกใช้ไปป์ไลน์ DML การพยายามดำเนินการอ่านหลังจากไปป์ไลน์ DML ทำงานไม่สำเร็จพร้อมข้อผิดพลาด
FAILED_PRECONDITION:Cannot have reads after the first write in a Firestore transaction. - การดำเนินการนี้ขึ้นอยู่กับขีดจำกัดธุรกรรมของ Firestore รุ่น Enterprise
การดำเนินการที่ไม่ใช่ธุรกรรม
DML ที่ไม่ใช่ธุรกรรมได้รับการออกแบบมาสำหรับการแก้ไขเอกสารจำนวนมากพร้อมกันโดยไม่ติดข้อจำกัดด้านขนาดธุรกรรม การล็อกที่ระดับเอกสารแทนที่จะล็อกทั้งการดำเนินการจะช่วยให้การดำเนินการอื่นๆ ที่เกิดขึ้นพร้อมกันดำเนินต่อไปได้ขณะอัปเดตเอกสารในวงกว้าง
เมื่อขั้นตอน DML ทำงานนอกธุรกรรมที่ชัดเจน ให้ทำดังนี้
- การอัปเดตแบบอิสระและความสำเร็จบางส่วน: เอกสารแต่ละฉบับจะได้รับการอัปเดตแยกกัน และการดำเนินการจะไม่เป็นแบบอะตอมมิกในเอกสารต่างๆ ไปป์ไลน์จะหยุดทำงานเมื่อพบข้อผิดพลาดแรก และเอกสารที่แก้ไขก่อนหน้านี้จะยังคงเขียนลงในฐานข้อมูล ซึ่งช่วยให้ดำเนินการสำเร็จบางส่วนได้
- การรองรับสเตจ
- ระบบไม่รองรับระยะขั้นสูงและระยะแบบหลายการค้นหา (เช่น
aggregate(...),distinct(...),unnest(...),find_nearest(...),union(...), การรวม และการค้นหาย่อย) ก่อน DML นอกธุรกรรม ใช้ธุรกรรมหากไปป์ไลน์ของคุณต้องมีขั้นตอนเหล่านี้
- ระบบไม่รองรับระยะขั้นสูงและระยะแบบหลายการค้นหา (เช่น
- ขีดจำกัดการค้นหา 20 ครั้งของกฎความปลอดภัย: เอกสารแต่ละชุดจะดำเนินการในธุรกรรมของตนเองและประเมินกฎความปลอดภัยอีกครั้ง หากกฎความปลอดภัยใช้การค้นหา
get()หรือexists()แต่ละกลุ่มจะทำการค้นหา โดยจะถึงขีดจำกัดการค้นหา 20 ครั้งต่อคำขอหลังจากเขียนเอกสารประมาณ 200 รายการและไม่สำเร็จด้วยPERMISSION_DENIEDใช้การอ้างสิทธิ์ที่กำหนดเองแทนการค้นหาget()หรือexists()เพื่อหลีกเลี่ยงขีดจำกัดนี้
ข้อจำกัด
โปรดทราบข้อจำกัดต่อไปนี้สำหรับระยะ DML
- ระยะ DML ต้องเป็นระยะสุดท้ายในคำจำกัดความไปป์ไลน์ก่อนเรียกใช้
.execute() - เมื่อเรียกใช้นอกธุรกรรม เอกสารแต่ละรายการจะอัปเดตแยกกันและอาจทำให้เกิดความสำเร็จบางส่วน
- การดำเนินการ DML ที่ไม่ใช่ธุรกรรมซึ่งอยู่ภายใต้กฎความปลอดภัยที่มีการค้นหา
get()หรือexists()จะถูกจำกัดไว้ที่เอกสารประมาณ 200 รายการเนื่องจากขีดจำกัดการค้นหา 20 รายการ - การดำเนินการ DML แบบธุรกรรมจะถูกจำกัดโดยขีดจำกัดธุรกรรมของ Firestore Enterprise Edition เนื่องจากธุรกรรม Firestore ไม่อนุญาตให้อ่านหลังจากเขียนครั้งแรก คุณจึงไม่สามารถเรียกใช้ไปป์ไลน์ DML หลายครั้งภายในธุรกรรมเดียว และไม่สามารถอ่านเอกสารหลังจากเรียกใช้ไปป์ไลน์ DML ได้
การพยายามดำเนินการอ่านหลังจากเขียน DML ไม่สำเร็จพร้อมข้อผิดพลาด
FAILED_PRECONDITION:Cannot have reads after the first write in a Firestore transaction. - หากขั้นตอนก่อนหน้าขั้นตอน DML สร้างเอกสารหลายรายการที่มี
__name__เดียวกันหรือประเมินเป็นรหัสเอกสารปลายทางเดียวกัน ระบบจะประมวลผลการเปลี่ยนแปลงแต่ละรายการตามลำดับ ดังนี้- สำหรับ
upsert(...)และupdate(...): การเปลี่ยนแปลงหลายรายการที่กำหนดเป้าหมายไปยังเอกสารเดียวกันจะเป็นไปตามความหมาย "รายการสุดท้ายชนะ" โดยการเปลี่ยนแปลงที่ประมวลผลล่าสุดจะเป็นตัวกำหนดสถานะสุดท้ายของเอกสาร - สำหรับ
delete(...): การพยายามครั้งแรกจะลบเอกสาร และการพยายามครั้งต่อๆ ไปสำหรับเอกสารเดียวกันจะไม่ดำเนินการใดๆ - สำหรับ
insert(...): การพยายามครั้งแรกจะสร้างเอกสาร และการพยายามครั้งต่อๆ ไปที่กำหนดเป้าหมายรหัสเอกสารเดียวกันจะล้มเหลวพร้อมข้อผิดพลาดALREADY_EXISTS
- สำหรับ