update(...) এবং delete(...) ডেটা ম্যানিপুলেশন ল্যাঙ্গুয়েজ (DML)
স্টেজের মাধ্যমে ডেটা পাইপলাইন তৈরি করুন
যা ডকুমেন্টের জন্য কোয়েরি করতে এবং তারপর ডেটা মুছে ফেলতে বা পরিবর্তন করতে পারে।
সংস্করণ সংক্রান্ত প্রয়োজনীয়তা
এই পৃষ্ঠায় যেসব অপারেশন বর্ণনা করা হয়েছে সেগুলির জন্য Firestore Enterprise সংস্করণ প্রয়োজন।
শুরু করার আগে
পাইপলাইন অপারেশনের মাধ্যমে ডেটাবেস কোয়েরি কীভাবে করতে হয় তা আপনাকে জানতে হবে।
ডকুমেন্ট আপডেট করুন
ডেটা পাইপলাইন তৈরি করতে 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() )
জাভা
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)
ডকুমেন্ট মুছুন
ডেটা পাইপলাইন তৈরি করতে delete(...) DML স্টেজ ব্যবহার করুন
যা ডকুমেন্টের জন্য কোয়েরি করতে এবং তারপর ডেটা মুছে ফেলতে পারে।
ভুলবশত বাল্ক ডিলিট করা আটকাতে, delete(...)-এ শেষ হওয়া পাইপলাইনে
অন্তত একটি where(...) স্টেজ থাকতে হবে।
সব DML স্টেজ অবশ্যই পাইপলাইনের শেষে আসতে হবে।
যেমন, নিম্নলিখিত পাইপলাইনটি address.users-এর মান USA-এ সেট করা এবং __create_time__-এর মান ১০ দিনের কম থাকা সমস্ত 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() )
জাভা
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, ডকুমেন্ট জুড়ে অ্যাটমিক, অল-অর-নাথিং কনসিস্টেন্সি প্রদান করে এবং পাইপলাইন কোয়েরি স্টেজের সম্পূর্ণ সেটকে সাপোর্ট করে। এর ফলে, এটি এমন ওয়ার্কলোডের জন্য আদর্শ হয়ে ওঠে যেখানে কঠোর ধারাবাহিকতার গ্যারান্টি প্রয়োজন—যেখানে আংশিক আপডেট গ্রহণযোগ্য নয়—অথবা যা জটিল কোয়েরি স্টেজের উপর নির্ভর করে, তবে শর্ত হল যে পরিবর্তনগুলি ট্রানজ্যাকশন সাইজের সীমার মধ্যে থাকতে হবে।
স্পষ্ট ট্রানজ্যাকশনের (runTransaction /
transaction.execute(pipeline) বা atomic: true বিকল্প ব্যবহার করে) মধ্যে DML পাইপলাইন চালানোর ক্ষেত্রে নিম্নলিখিত
আচরণ দেখা যায়:
- সব মিউটেশন একসাথে কমিট করা হয় অথবা ব্যর্থ হলে সম্পূর্ণভাবে রোল ব্যাক করা হয়।
- 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-এর আগে কাজ করে না। আপনার পাইপলাইনে এইসব ধাপের প্রয়োজন হলে ট্রানজ্যাকশন ব্যবহার করুন।
- উন্নত ও মাল্টি-কোয়েরি স্টেজ (যেমন
- নিরাপত্তা সংক্রান্ত নিয়মের ২০-লুকআপ সীমা: ডকুমেন্টের প্রতিটি ব্যাচ নিজস্ব ট্রানজ্যাকশনে
এক্সিকিউট হয় এবং নিরাপত্তা সংক্রান্ত নিয়ম আবার মূল্যায়ন করে। আপনার নিরাপত্তা সংক্রান্ত নিয়মে
get()বাexists()লুকআপ ব্যবহার করা হলে, প্রতিটি ব্যাচ একটি লুকআপ এক্সিকিউট করে, যা প্রায় ২০০টি ডকুমেন্ট লেখার পরে প্রতি-অনুরোধে ২০টি লুকআপের সীমায় পৌঁছে যায় এবংPERMISSION_DENIED-এর সাথে ব্যর্থ হয়। এই সীমা এড়াতেget()বাexists()লুকআপের পরিবর্তে কাস্টম ক্লেম ব্যবহার করুন।
সীমাবদ্ধতা
DML স্টেজের জন্য নিম্নলিখিত সীমাবদ্ধতাগুলি মনে রাখবেন:
.execute()কল করার আগে পাইপলাইন সংজ্ঞায় DML স্টেজ অবশ্যই শেষ স্টেজ হতে হবে।- ট্রানজ্যাকশনের বাইরে রান করা হলে, প্রতিটি ডকুমেন্ট একে অপরের থেকে স্বাধীনভাবে আপডেট করা হয় এবং আংশিক সাফল্যের অনুমতি দেয়।
get()বাexists()লুকআপ সহ নিরাপত্তা সংক্রান্ত নিয়মের অধীনে থাকা নন-ট্রানজ্যাকশনাল DML অপারেশন ২০-লুকআপ সীমার কারণে প্রায় ২০০টি ডকুমেন্টে সীমাবদ্ধ।- ট্রানজ্যাকশন সংক্রান্ত DML অপারেশন Firestore Enterprise এডিশন
ট্রানজ্যাকশন সীমা দ্বারা সীমাবদ্ধ। 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সমস্যার কারণে তা ব্যর্থ হয়।