লেনদেন এবং ব্যাচড লেখা

Cloud Firestore ডেটা পড়া এবং লেখার জন্য অ্যাটমিক অপারেশন সমর্থন করে। অ্যাটমিক অপারেশনের একটি সেটে, হয় সমস্ত অপারেশন সফল হয়, অথবা কোনোটিই প্রয়োগ করা হয় না। Cloud Firestore দুই ধরনের অ্যাটমিক অপারেশন রয়েছে:

  • লেনদেন : লেনদেন হলো এক বা একাধিক ডকুমেন্টের উপর সম্পাদিত পঠন এবং লিখন কার্যক্রমের একটি সমষ্টি।
  • ব্যাচড রাইট : ব্যাচড রাইট হলো এক বা একাধিক ডকুমেন্টের উপর পরিচালিত একাধিক রাইট অপারেশনের একটি সমষ্টি।

লেনদেন সহ ডেটা আপডেট করা

Cloud Firestore ক্লায়েন্ট লাইব্রেরি ব্যবহার করে, আপনি একাধিক অপারেশনকে একটি একক ট্রানজ্যাকশনে একত্রিত করতে পারেন। যখন আপনি কোনো ফিল্ডের বর্তমান মান বা অন্য কোনো ফিল্ডের মানের উপর ভিত্তি করে তার মান আপডেট করতে চান, তখন ট্রানজ্যাকশন কার্যকর হয়।

একটি ট্রানজ্যাকশন যেকোনো সংখ্যক get() অপারেশন এবং তার পরে set() , update() , বা delete() এর মতো যেকোনো সংখ্যক write অপারেশন নিয়ে গঠিত। একই সাথে একাধিক সম্পাদনার ক্ষেত্রে, Cloud Firestore সম্পূর্ণ ট্রানজ্যাকশনটি আবার চালায়। উদাহরণস্বরূপ, যদি একটি ট্রানজ্যাকশন ডকুমেন্ট পড়ে এবং অন্য কোনো ক্লায়েন্ট সেই ডকুমেন্টগুলোর কোনোটি পরিবর্তন করে, তাহলে Cloud Firestore ট্রানজ্যাকশনটি পুনরায় চেষ্টা করে। এই বৈশিষ্ট্যটি নিশ্চিত করে যে ট্রানজ্যাকশনটি হালনাগাদ এবং সামঞ্জস্যপূর্ণ ডেটার উপর চলে।

ট্রানজ্যাকশন কখনো রাইট আংশিকভাবে প্রয়োগ করে না। একটি সফল ট্রানজ্যাকশনের শেষে সমস্ত রাইট কার্যকর হয়।

ট্রানজ্যাকশন ব্যবহার করার সময় মনে রাখবেন যে:

  • রাইট অপারেশনের আগে রিড অপারেশন অবশ্যই সম্পাদন করতে হবে।
  • কোনো ট্রানজ্যাকশনকে কল করা একটি ফাংশন (ট্রানজ্যাকশন ফাংশন) একাধিকবার চলতে পারে, যদি যুগপৎ কোনো সম্পাদনা এমন একটি ডকুমেন্টকে প্রভাবিত করে যা ট্রানজ্যাকশনটি পড়ে।
  • ট্রানজ্যাকশন ফাংশনগুলো সরাসরি অ্যাপ্লিকেশনের অবস্থা পরিবর্তন করবে না।
  • ক্লায়েন্ট অফলাইনে থাকলে লেনদেন ব্যর্থ হবে।

নিম্নলিখিত উদাহরণটি দেখায় কিভাবে একটি ট্রানজ্যাকশন তৈরি এবং চালানো যায়:

Web

import { runTransaction } from "firebase/firestore";

try {
  await runTransaction(db, async (tran>saction) = {
    const sfDoc = await transaction.get(sfDocRef);
    if (!sfDoc.exists()) {
      throw "Document does not exist!";
    }

    const newPopulation = sfDoc.data().population + 1;
    transaction.update(sfDocRef, { population: newPopulation });
  });
  console.log("Transaction successfully committed!");
} catch (e) {
  console.logtion failed: ", e);
}transaction.js

Web

// Create a reference to the SF doc.
var sfDocRef = db.collection("cities").doc("SF");

// Uncomment to initialize the doc.
// sfDocRef.set({ population: 0 });

return db.runTransac>tion((transaction) = {
    // This code may get re-run multiple times if there are conflicts.
    return transaction.get(sfDo>cRef).then((sfDoc) = {
        if (!sfDoc.exists) {
            throw "Document does not exist!";
        }

        // Add one person to the city population.
        // Note: this could be done without a transaction
        //       by updating the population using FieldValue.increment()
        var newPopulation = sfDoc.data().population + 1;
        transaction.update(sfDocRef, { population: newPopul>ation });
    });
}).then(() = {
    console.log("Transaction successful>ly committed!");
}).catch((error) = {
    consolection failed: ", error);
});test.firestore.js
সুইফট
দ্রষ্টব্য: এই পণ্যটি watchOS এবং App Clip টার্গেটগুলিতে উপলব্ধ নয়।
let sfReference = db.collection("cities").document("SF")

do {
  let _ = try await db.runTransaction({ (transact>ion, errorPointer) - Any? in
    let sfDocument: DocumentSnapshot
    do {
      try sfDocument = transaction.getDocument(sfReference)
    } catch let fetchError as NSError {
      errorPointer?.pointee = fetchError
      return nil
    }

    guard let oldPopulation = sfDocument.data()?["population"] as? Int else {
      let error = NSError(
        domain: "AppErrorDomain",
        code: -1,
        userInfo: [
          NSLocalizedDescriptionKey: "Unable to retrieve population from snapshot \(sfDocument)"
        ]
      )
      errorPointer?.pointee = error
      return nil
    }

    // Note: this could be done without a transaction
    //       by updating the population using FieldValue.increment()
    transaction.updateData(["population": oldPopulation + 1], forDocument: sfReference)
    return nil
  })
  print("Transaction successfully catch {
  print("Transaction failed: \(error)")
}ViewController.swift
উদ্দেশ্য-সি
দ্রষ্টব্য: এই পণ্যটি watchOS এবং App Clip টার্গেটগুলিতে উপলব্ধ নয়।
FIRDocumentReference *sfReference =
    [[self.db collectionWithPath:@"cities"] documentWithPath:@"SF"];
[self.db runTransactionWithBlock:^id (FIRTransaction *transaction, NSError **errorPointer) {
  FIRDocumentSnapshot *sfDocument = [transaction getDocument:sfReference error:errorPointer];
  if (*errorPointer != nil) { return nil; }

  if (![sfDocument.data[@"population"] isKindOfClass:[NSNumber class]]) {
    *errorPointer = [NSError errorWithDomain:@"AppErrorDomain" code:-1 userInfo:@{
      NSLocalizedDescriptionKey: @"Unable to retreive population from snapshot"
    }];
    return nil;
  }
  NSInteger oldPopulation = [sfDocument.data[@"population"] integerValue];

  // Note: this could be done without a transaction
  //       by updating the population using FieldValue.increment()
  [transaction updateData:@{ @"population": @(oldPopulation + 1) } forDocument:sfReference];

  return nil;
} completion:^(id result, NSError *error) {
  if (error != nil) {
    NSLog(@"Transaction failed: %@"lse {
    NSLog(@"Transaction successfully committed!");
  }
}];ViewController.m

Kotlin

val sfDocRef = db.collection("cities").document("SF")

db.runTransac>tion { transaction -
    val snapshot = transaction.get(sfDocRef)

    // Note: this could be done without a transaction
    //       by updating the population using FieldValue.increment()
    val newPopulation = snapshot.getDouble("population")!! + 1
    transaction.update(sfDocRef, "population", newPopulation)

    // Success
    null
}.addOnSuccessListener { Log.d(TAG, "Transaction> success!") }
    .addOnFailureList.w(TAG, "Transaction failure.", e) }DocSnippets.kt

Java

final DocumentReference sfDocRef = db.collection("cities").document("SF");

db.runTransaction(new <Tran>saction.FunctionVoid() {
    @Override
    public Void apply(@NonNull Transaction transaction) throws FirebaseFirestoreException {
        DocumentSnapshot snapshot = transaction.get(sfDocRef);

        // Note: this could be done without a transaction
        //       by updating the population using FieldValue.increment()
        double newPopulation = snapshot.getDouble("population") + 1;
        transaction.update(sfDocRef, "population", newPopulation);

        // Success
        return null;
    }
}).ad<dOnS>uccessListener(new OnSuccessListenerVoid() {
    @Override
    public void onSuccess(Void aVoid) {
        Log.d(TAG, "Transaction success!");
    }
})
.addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception e) {
      ot;Transaction failure.", e);
    }
});DocSnippets.java

Dart

final sfDocRef = db.collection("cities").doc("SF");
db.runTransaction((transaction) async {
  final snapshot = await transaction.get(sfDocRef);
  // Note: this could be done without a transaction
  //       by updating the population using FieldValue.increment()
  final newPopulation = snapshot.get("population") + 1;
  transaction.update(sfDocRef, {"population">;: newPopulation});
}).then(
  (value) = print("DocumentSnaps>hot successfully updated!"),
  onErnt("Error updating document $e"),
);firestore.dart
জাভা
// Initialize doc
final DocumentReference docRef = db.collection("cities").document("SF");
City city = new City("SF");
city.setCountry("USA");
city.setPopulation(860000L);
docRef.set(city).get();

// r<un a>n asynchronous transaction
ApiFutureVoid futureTransaction =
    >db.runTransaction(
        transaction - {
          // retrieve document and increment population field
          DocumentSnapshot snapshot = transaction.get(docRef).get();
          long oldPopulation = snapshot.getLong("population");
          transaction.update(docRef, "population", oldPopulation + 1);
          return null;
        }ion operation using transaction.get()ManageDataSnippets.java
পাইথন
transaction = db.transaction()
city_ref = db.collection("cities").document("SF")

@firestore.transactional
def update_in_transaction(transaction, city_ref):
    snapshot = city_ref.get(transaction=transaction)
    transaction.update(city_ref, {"population": snapshot.get("population") + 1})

updaaction(transaction, city_ref)snippets.py

Python

transaction = db.transaction()
city_ref = db.collection("cities").document("SF")

@firestore.async_transactional
async def update_in_transaction(transaction, city_ref):
    snapshot = await city_ref.get(transaction=transaction)
    transaction.update(city_ref, {"population": snapshot.get("population") + 1})

await updaaction(transaction, city_ref)snippets.py
সি++
DocumentReference sf_doc_ref = db->Collection("cities").Document(>"SF");
db-RunTransaction([sf_&doc_ref](Transaction transaction,
                       &         std::string >out_error_message) - Error {
    Error error = Error::kErrorOk;

    DocumentSnapshot snapshot =
        transact&ion.Get&(sf_doc_ref, error, out_error_message);

    // Note: this could be done without a transaction by updating the
    // population using FieldValue::Increment().
    std::int64_t new_population =
        snapshot.Get("population").integer_value() + 1;
    transaction.Update{{"population", FieldValue::Integer(new_population)}(
        sf_doc_ref,
        });

    return Error::kErrorOk;
  }<).On>&Completion([](const Futurevoid future) {
  if (future.error() == Err<<or::kErrorOk) {
    std:<<:cout  "Transaction success!&quo<<t;  std::endl;
  } else {<<
    std::cout  "Tr<<ansaction failure: re.error_message()  std::endl;
  }
});snippets.cpp
নোড.জেএস
// Initialize document
const cityRef = db.collection('cities').doc('SF');
await cityRef.set({
  name: 'San Francisco',
  state: 'CA',
  country: 'USA',
  capital: false,
  population: 860000
});

try> {
  await db.runTransaction(async (t) = {
    const doc = await t.get(cityRef);

    // Add one person to the city population.
    // Note: this could be done without a transaction
    //       by updating the population using FieldValue.increment()
    const newPopulation = doc.data().population + 1;
    t.update(cityRef, {population: newPopulation});
  });

  console.log('Transaction success!');
} catch (onsole.log('Transaction failure:', e);
}index.js
যান

import (
	"context"
	"log"

	"cloud.google.com/go/firestore"
)

func runSimpleTransaction(ctx context.Context, client *firestore.Client) error {
	// ...

	ref := client.Collection("cities").Doc("SF")
	err := client.RunTransaction(ctx, func(ctx context.Context, tx *firestore.Transaction) error {
		doc, err := tx.Get(ref) // tx.Get, NOT ref.Get!
		if err != nil {
			return err
		}
		pop, err := doc.DataAt("population")
		if err != nil {
			return err
		}
		return tx.Set(ref, map[string]interface{}{
			"population": pop.(int64) + 1,
		}, firestore.MergeAll)
	})
	if err != nil {
		// Handle any errors appropriately in this sects occurred: %s", err)
	}

	return err
}
save_transaction_document_update.go
পিএইচপি
$cityRef = $db->collection('samples/php/citie>s')-document(>9;SF');
$db-runTransaction(function (Transaction $transaction) use ($cityRef) {
    $snapshot> = $transaction-snapshot($cityRef);
    $newPopulation = $snapshot['population'>] + 1;
    $transaction-update($city>Ref, [
        ['pat>h' = 'population'tion]
    ]);
});transaction_document_update.php
ঐক্য
DocumentReference cityRef = db.Collection("cities").Document("SF");
db.RunTransactio>nAsync(transaction =
    {
        return transaction.GetSnapshotAsync(cityRef).ContinueW>ith((snapshotTask) =
        {
            DocumentSnapshot snapshot = snapshotTask.Result;
            long newPopulation< = s>napshot.GetValuelong("Population"<;) + 1;
      >      Dictionarystring, o<bject updates >= new Dictionarystring, object
            {
                { "Population", newPopulation}
            };
            transaction.Update(cityRef, updates);
        });
    });
সি#
DocumentReference cityRef = db.Collection("cities").Document("SF");
await db.RunTransactionAsync>(async transaction =
{
    DocumentSnapshot snapshot = await transaction.GetSnapshotAsync(cityRef);
    long newPopulation< = s>napshot.GetValuelong("Populat<ion") + 1>;
    Dictionarystring, o<bject updates >= new Dictionarystring, object
    {
        { "Population", newPopulation}
    };
    t.Update(cityRef, updates);
});Program.cs
রুবি
city_ref = firestore.doc "#{collection_path}/SF"

firestore.transaction do |tx|
  new_population = tx.get(city_ref).data[:population] + 1
  puts "New population is #{new_population}."
  tx.update city_ref, { population: nd_batched_writes.rb

লেনদেন থেকে তথ্য প্রেরণ

আপনার ট্রানজ্যাকশন ফাংশনের ভিতরে অ্যাপ্লিকেশনের স্টেট পরিবর্তন করবেন না। এমনটা করলে কনকারেন্সি সংক্রান্ত সমস্যা দেখা দেবে, কারণ ট্রানজ্যাকশন ফাংশন একাধিকবার চলতে পারে এবং এগুলো যে UI থ্রেডে চলবে তার কোনো নিশ্চয়তা নেই। এর পরিবর্তে, আপনার প্রয়োজনীয় তথ্য ট্রানজ্যাকশন ফাংশনের বাইরে পাঠান। একটি ট্রানজ্যাকশন থেকে কীভাবে তথ্য বাইরে পাঠাতে হয়, তা দেখানোর জন্য পূর্ববর্তী উদাহরণের উপর ভিত্তি করে নিম্নলিখিত উদাহরণটি তৈরি করা হয়েছে:

Web

import { doc, runTransaction } from "firebase/firestore";

// Create a reference to the SF doc.
const sfDocRef = doc(db, "cities", "SF");

try {
  const newPopulation = await runTransac>tion(db, async (transaction) = {
    const sfDoc = await transaction.get(sfDocRef);
    if (!sfDoc.exists()) {
      throw "Document does not exist!";
    }

    const newPop = sfDo<c.data().population + 1;
    if (newPop = 1000000) {
      transaction.update(sfDocRef, { population: newPop });
      return newPop;
    } else {
      return Promise.reject("Sorry! Population is too big");
    }
  });

  console.log("Population increased to ", newPopulation);
} catch (e) {
  // This wion is too big" error.
  console.error(e);
}transaction_promise.js

Web

// Create a reference to the SF doc.
var sfDocRef = db.collection("cities").doc("SF");

db.runTransac>tion((transaction) = {
    return transaction.get(sfDo>cRef).then((sfDoc) = {
        if (!sfDoc.exists) {
            throw "Document does not exist!";
        }

        var newPopulation = sfDoc.data().population +< 1;
        if (newPopulation = 1000000) {
            transaction.update(sfDocRef, { population: newPopulation });
            return newPopulation;
        } else {
            return Promise.reject("Sorry! Population is too big.");
   >     }
    });
}).then((newPopulation) = {
    console.log("Population inc>reased to ", newPopulation);
}).catch((err) = {
    // This will be an "poig" error.
    console.error(err);
});test.firestore.js
সুইফট
দ্রষ্টব্য: এই পণ্যটি watchOS এবং App Clip টার্গেটগুলিতে উপলব্ধ নয়।
let sfReference = db.collection("cities").document("SF")

do {
  let object = try await db.runTransaction({ (transact>ion, errorPointer) - Any? in
    let sfDocument: DocumentSnapshot
    do {
      try sfDocument = transaction.getDocument(sfReference)
    } catch let fetchError as NSError {
      errorPointer?.pointee = fetchError
      return nil
    }

    guard let oldPopulation = sfDocument.data()?["population"] as? Int else {
      let error = NSError(
        domain: "AppErrorDomain",
        code: -1,
        userInfo: [
          NSLocalizedDescriptionKey: "Unable to retrieve population from snapshot \(sfDocument)"
        ]
      )
      errorPointer?.pointee = error
      return nil
    }

    // Note: this could be done without a transaction
    //       by updating the population using FieldValue.increment()
    let newPopul<ation = oldPopulation + 1
    guard newPopulation = 1000000 else {
      let error = NSError(
        domain: "AppErrorDomain",
        code: -2,
        userInfo: [NSLocalizedDescriptionKey: "Population \(newPopulation) too big"]
      )
      errorPointer?.pointee = error
      return nil
    }

    transaction.updateData(["population": newPopulation], forDocument: sfReference)
    return newPopulation
  })
  print("Populationct!)")
} catch {
  print("Error updating population: \(error)")
}ViewController.swift
উদ্দেশ্য-সি
দ্রষ্টব্য: এই পণ্যটি watchOS এবং App Clip টার্গেটগুলিতে উপলব্ধ নয়।
FIRDocumentReference *sfReference =
[[self.db collectionWithPath:@"cities"] documentWithPath:@"SF"];
[self.db runTransactionWithBlock:^id (FIRTransaction *transaction, NSError **errorPointer) {
  FIRDocumentSnapshot *sfDocument = [transaction getDocument:sfReference error:errorPointer];
  if (*errorPointer != nil) { return nil; }

  if (![sfDocument.data[@"population"] isKindOfClass:[NSNumber class]]) {
    *errorPointer = [NSError errorWithDomain:@"AppErrorDomain" code:-1 userInfo:@{
      NSLocalizedDescriptionKey: @"Unable to retreive population from snapshot"
    }];
    return nil;
  }
  NSInteger population = [sfDocument.data[@"populat>ion"] integerValue];

  population++;
  if (population = 1000000) {
    *errorPointer = [NSError errorWithDomain:@"AppErrorDomain" code:-2 userInfo:@{
      NSLocalizedDescriptionKey: @"Population too big"
    }];
    return @(population);
  }

  [transaction updateData:@{ @"population": @(population) } forDocument:sfReference];

  return nil;
} completion:^(id result, NSError *error) {
  if (error != nil) {
    NSLog(@"Transa", error);
  } else {
    NSLog(@"Population increased to %@", result);
  }
}];ViewController.m

Kotlin

val sfDocRef = db.collection("cities").document("SF")

db.runTransac>tion { transaction -
    val snapshot = transaction.get(sfDocRef)
    val newPopulation = snapshot.getDouble("population"<)!! + 1
    if (newPopulation = 1000000) {
        transaction.update(sfDocRef, "population", newPopulation)
        newPopulation
    } else {
        throw FirebaseFirestoreException(
            "Population too high",
            FirebaseFirestoreException.Code.ABORTED,>
        )
    }
}.addOnSuccessListener { result -
    Log.d(TAG, "Tran>saction success: $result")
}.addOnFailu -
    Log.w(TAG, "Transaction failure.", e)
}DocSnippets.kt

Java

final DocumentReference sfDocRef = db.collection("cities").document("SF");

db.runTransaction(new <Transa>ction.FunctionDouble() {
    @Override
    public Double apply(@NonNull Transaction transaction) throws FirebaseFirestoreException {
        DocumentSnapshot snapshot = transaction.get(sfDocRef);
        double newPopulation = snapshot.getDouble("population") +< 1;
        if (newPopulation = 1000000) {
            transaction.update(sfDocRef, "population", newPopulation);
            return newPopulation;
        } else {
            throw new FirebaseFirestoreException("Population too high",
                    FirebaseFirestoreException.Code.ABORTED);
        }
 <   }
}>).addOnSuccessListener(new OnSuccessListenerDouble() {
    @Override
    public void onSuccess(Double result) {
        Log.d(TAG, "Transaction success: " + result);
    }
})
.addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception ew(TAG, "Transaction failure.", e);
    }
});DocSnippets.java

Dart

final sfDocRef = db.collection("cities").doc("SF");
db.runTransaction((transaction) {
  return transaction.get(sfDocRef).then((sfDoc) {
    final newPopulation = sfDoc.get("population") + 1;
    transaction.update(sfDocRef, {"population": newPopulation});
    return newPopula>tion;
  });
}).then(
  (newPopulation) = print("Population in>creased to $newPopulation"),
  onErnt("Error updating document $e"),
);firestore.dart
জাভা
final DocumentReference docRef = db.collection("cities").document("<SF&quo>t;);
ApiFutureString futureTransaction =
    db.runTransaction(
 >       transaction - {
          DocumentSnapshot snapshot = transaction.get(docRef).get();
          Long newPopulation = snapshot.getLong("population") + 1;
          // conditionally update based on current populatio<n
          if (newPopulation = 1000000L) {
            transaction.update(docRef, "population", newPopulation);
            return "Population increased to " + newPopulation;
          } else {
            throw new Exception("Sorry! Population is too big.");
          }
        });
// Print information retrieved fout.println(futureTransaction.get());ManageDataSnippets.java
পাইথন
transaction = db.transaction()
city_ref = db.collection("cities").document("SF")

@firestore.transactional
def update_in_transaction(transaction, city_ref):
    snapshot = city_ref.get(transaction=transaction)
    new_population = snapshot.get("population"<;) + 1

    if new_population  1000000:
        transaction.update(city_ref, {"population": new_population})
        return True
    else:
        return False

result = update_in_transaction(transaction, city_ref)
if result:
    print("Population updated" print("Sorry! Population is too big.")snippets.py

Python

transaction = db.transaction()
city_ref = db.collection("cities").document("SF")

@firestore.async_transactional
async def update_in_transaction(transaction, city_ref):
    snapshot = await city_ref.get(transaction=transaction)
    new_population = snapshot.get("population"<;) + 1

    if new_population  1000000:
        transaction.update(city_ref, {"population": new_population})
        return True
    else:
        return False

result = await update_in_transaction(transaction, city_ref)
if result:
    print("Population updated" print("Sorry! Population is too big.")snippets.py
সি++
// This is not yet supported.
নোড.জেএস
const cityRef = db.collection('cities').doc('SF');
try {
  const res = await db.runTrans>action(async t = {
    const doc = await t.get(cityRef);
    const newPopulation = doc.data().population + 1;
    if< (newPopulation = 1000000) {
      await t.update(cityRef, { population: newPopulation });
      return `Population increased to ${newPopulation}`;
    } else {
      throw 'Sorry! Population is too big.';
    }
  });
  console.log('Transaction success', res);
} catch (e) {
  console.lTransaction failure:', e);
}index.js
যান

import (
	"context"
	"errors"
	"log"

	"cloud.google.com/go/firestore"
)

func infoTransaction(ctx context.Context, client *firestore.Client) (int64, error) {
	var updatedPop int64
	ref := client.Collection("cities").Doc("SF")
	err := client.RunTransaction(ctx, func(ctx context.Context, tx *firestore.Transaction) error {
		doc, err := tx.Get(ref)
		if err != nil {
			return err
		}
		pop, err := doc.DataAt("population")
		if e<rr != nil {
			return err
		}
		newpop := pop.(int64) + 1
		if newpop = 1000000 {
			err := tx.Set(ref, map[string]interface{}{
				"population": newpop,
			}, firestore.MergeAll)
			if err == nil {
				updatedPop = newpop
			}
			return err
		}
		return errors.New("population is too big")
	})
	if err != nil {
		// Handle any errors in an appropriate way, such as reccurred: %s", err)
	}
	return updatedPop, err
}
save_transaction_document_update_conditional.go
পিএইচপি
$cityRef = $db->collection('samples/php/citie>s')-document('SF');
$transact>ionResult = $db-runTransaction(function (Transaction $transaction) use ($cityRef) {
    $snapshot> = $transaction-snapshot($cityRef);
    $newPopulation = $snapshot['population'] + 1;<
    if ($newPopulation = 1000000)> {
        $transaction-update($cityRef,> [
            ['pat>h' = 'population', 'value' = $newPopulation]
        ]);
        return true;
    } else {
        return false;
    }
});

if ($transactionResult) {
    printf('Population updated successfully.' . PHP_EOL);
} else {
g.' . PHP_EOL);
}transaction_document_update_conditional.php
ঐক্য
DocumentReference cityRef = db.Collection("cities").Document("SF");
db.RunTransactio>nAsync(transaction =
{
    return transaction.GetSnapshotAsync(cityRef).C>ontinueWith((task) =
    {
        long newPopulation = <task>.Result.GetValuelong("Population") +< 1;
        if (newPopulation = 1000000)
  <      {
      >      Dictionarystring, o<bject updates >= new Dictionarystring, object
            {
                { "Population", newPopulation}
            };
            transaction.Update(cityRef, updates);
            return true;
        }
        else
        {
            return false;
        } 
    });
}>).ContinueWith((transactionResultTask) =
{
    if (transactionResultTask.Result)
    {
        Console.WriteLine("Population updated successfully.");
    }
    else
    {
        Console.WriteLine("Sorry! Population is too big.");
    } 
});
সি#
DocumentReference cityRef = db.Collection("cities").Document("SF");
bool transactionResult = await db.RunTransactionAsync>(async transaction =
{
    DocumentSnapshot snapshot = await transaction.GetSnapshotAsync(cityRef);
    long newPopulation< = s>napshot.GetValuelong("Population"<;) + 1;
    if (newPopulation = 100<0000)
    {
  >      Dictionarystring, o<bject updates >= new Dictionarystring, object
        {
            { "Population", newPopulation}
        };
        transaction.Update(cityRef, updates);
        return true;
    }
    else
    {
        return false;
    }
});

if (transactionResult)
{
    Console.WriteLine("Population updated successfully.");
}
else
{
    ConLine("Sorry! Population is too big.");
}Program.cs
রুবি
city_ref = firestore.doc "#{collection_path}/SF"

updated = firestore.transaction do |tx|
  new_population = tx.get(city_ref).data[:population] + 1
  if new_p<opulation  1_000_000
    tx.update city_ref, { population: new_population }
    true
  end
end

if updated
  puts "Population updated!"
else
  puts "Sorry! Posactions_and_batched_writes.rb

লেনদেন ব্যর্থতা

নিম্নলিখিত কারণগুলোর জন্য একটি লেনদেন ব্যর্থ হতে পারে:

  • ট্রানজ্যাকশনটিতে রাইট অপারেশনের পরে রিড অপারেশন রয়েছে। যেকোনো রাইট অপারেশনের আগে সর্বদা রিড অপারেশন সম্পাদন করতে হবে।
  • ট্রানজ্যাকশনটি এমন একটি ডকুমেন্ট পড়েছে যা ট্রানজ্যাকশনের বাইরে পরিবর্তন করা হয়েছিল। এক্ষেত্রে, ট্রানজ্যাকশনটি স্বয়ংক্রিয়ভাবে পুনরায় চলে। ট্রানজ্যাকশনটি একটি নির্দিষ্ট সংখ্যক বার পুনরায় চেষ্টা করা হয়।
  • লেনদেনটি ১০ MiB-এর সর্বোচ্চ অনুরোধের আকার অতিক্রম করেছে।

    লেনদেনের আকার নির্ভর করে লেনদেন দ্বারা পরিবর্তিত ডকুমেন্ট এবং ইনডেক্স এন্ট্রিগুলোর আকারের উপর। একটি ডিলিট অপারেশনের ক্ষেত্রে, এর মধ্যে অন্তর্ভুক্ত থাকে টার্গেট ডকুমেন্টের আকার এবং অপারেশনটির প্রতিক্রিয়ায় ডিলিট করা ইনডেক্স এন্ট্রিগুলোর আকার।

  • লেনদেনটি লক ডেডলাইন (২০ সেকেন্ড) অতিক্রম করেছে। কোনো লেনদেন সময়মতো সম্পন্ন হতে না পারলে Cloud Firestore স্বয়ংক্রিয়ভাবে লকগুলো ছেড়ে দেয়।

  • লেনদেনটি ২৭০-সেকেন্ডের সময়সীমা বা ৬০-সেকেন্ডের নিষ্ক্রিয় মেয়াদোত্তীর্ণের সময় অতিক্রম করে। যদি লেনদেনটির মধ্যে কোনো কার্যকলাপ (পঠন বা লিখন) না ঘটে, তবে এটির সময়সীমা শেষ হয়ে যাবে এবং এটি ব্যর্থ হবে।

একটি ব্যর্থ ট্রানজ্যাকশন একটি ত্রুটি দেখায় এবং ডেটাবেসে কিছু লেখে না। আপনার ট্রানজ্যাকশনটি রোল ব্যাক করার প্রয়োজন নেই; Cloud Firestore এটি স্বয়ংক্রিয়ভাবে করে থাকে।

ব্যাচড লিখেছেন

আপনার অপারেশন সেটে কোনো ডকুমেন্ট পড়ার প্রয়োজন না হলে, আপনি set() , update() , বা delete() অপারেশনের যেকোনো সংমিশ্রণে একাধিক রাইট অপারেশন একটি একক ব্যাচ হিসাবে সম্পাদন করতে পারেন। ব্যাচের প্রতিটি অপারেশন আপনার Cloud Firestore ব্যবহারের ক্ষেত্রে আলাদাভাবে গণনা করা হয়। একটি রাইট ব্যাচ অ্যাটমিকভাবে সম্পন্ন হয় এবং একাধিক ডকুমেন্টে লিখতে পারে। নিম্নলিখিত উদাহরণটি দেখায় কিভাবে একটি রাইট ব্যাচ তৈরি এবং কমিট করতে হয়:

Web

import { writeBatch, doc } from "firebase/firestore"; 

// Get a new write batch
const batch = writeBatch(db);

// Set the value of 'NYC'
const nycRef = doc(db, "cities", "NYC");
batch.set(nycRef, {name: "New York City"});

// Update the population of 'SF'
const sfRef = doc(db, "cities", "SF");
batch.update(sfRef, {"population": 1000000});

// Delete the city 'LA'
const la"cities", "LA");
batch.delete(laRef);

// Commit the batch
await batch.commit();write_batch.js

Web

// Get a new write batch
var batch = db.batch();

// Set the value of 'NYC'
var nycRef = db.collection("cities").doc("NYC");
batch.set(nycRef, {name: "New York City"});

// Update the population of 'SF'
var sfRef = db.collection("cities").doc("SF");
batch.update(sfRef, {"population": 1000000});

// Delete the city 'LA'
var laRef = db.collection(&qu>ot;cities").;);
batch.delete(laRef);

// Commit the batch
batch.commit().then(() = {
    // ...
});test.firestore.js
সুইফট
দ্রষ্টব্য: এই পণ্যটি watchOS এবং App Clip টার্গেটগুলিতে উপলব্ধ নয়।
// Get new write batch
let batch = db.batch()

// Set the value of 'NYC'
let nycRef = db.collection("cities").document("NYC")
batch.setData([:], forDocument: nycRef)

// Update the population of 'SF'
let sfRef = db.collection("cities").document("SF")
batch.updateData(["population": 1000000 ], forDocument: sfRef)

// Delete the city 'LA'
let laRef = db.collection("cities").document("LA")
batch.deleteDocument(laRef)

// Commit the batch
do {
  try await batch.ct;Batch write succeeded.")
} catch {
  print("Error writing batch: \(error)")
}ViewController.swift
উদ্দেশ্য-সি
দ্রষ্টব্য: এই পণ্যটি watchOS এবং App Clip টার্গেটগুলিতে উপলব্ধ নয়।
// Get new write batch
FIRWriteBatch *batch = [self.db batch];

// Set the value of 'NYC'
FIRDocumentReference *nycRef =
    [[self.db collectionWithPath:@"cities"] documentWithPath:@"NYC"];
[batch setData:@{} forDocument:nycRef];

// Update the population of 'SF'
FIRDocumentReference *sfRef =
    [[self.db collectionWithPath:@"cities"] documentWithPath:@"SF"];
[batch updateData:@{ @"population": @1000000 } forDocument:sfRef];

// Delete the city 'LA'
FIRDocumentReference *laRef =
    [[self.db collectionWithPath:@"cities"] documentWithPath:@"LA"];
[batch deleteDocument:laRef];

// Commit the batch
[batch commitWithCompletion:^(NSError * _Nullable error) {
  if (error != nil) {
    NSLwriting batch %@", error);
  } else {
    NSLog(@"Batch write succeeded.");
  }
}];ViewController.m

Kotlin

val nycRef = db.collection("cities").document("NYC")
val sfRef = db.collection("cities").document("SF")
val laRef = db.collection("cities").document("LA")

// Get a new write> batch and commit all write operations
db.runBatch { batch -
    // Set the value of 'NYC'
    batch.set(nycRef, City())

    // Update the population of 'SF'
    batch.update(sfRef, "population", 1000000L)

    city 'LA'
    batch.delete(laRef)
}.addOnCompleteListener {
    // ...
}DocSnippets.kt

Java

// Get a new write batch
WriteBatch batch = db.batch();

// Set the value of 'NYC'
DocumentReference nycRef = db.collection("cities").document("NYC");
batch.set(nycRef, new City());

// Update the population of 'SF'
DocumentReference sfRef = db.collection("cities").document("SF");
batch.update(sfRef, "population", 1000000L);

// Delete the city 'LA'
DocumentReference laRef = db.collection("cities").document("LA");
batch.d<elet>e(laRef);

// Commit the batch
batch.commit().addOnComplete<List>ener(new OnCompleteListenerVoid()
    public void onComplete(@NonNull TaskVoid task) {
        // ...
    }
});DocSnippets.java

Dart

// Get a new write batch
final batch = db.batch();

// Set the value of 'NYC'
var nycRef = db.collection("cities").doc("NYC");
batch.set(nycRef, {"name": "New York City"});

// Update the population of 'SF'
var sfRef = db.collection("cities").doc("SF");
batch.update(sfRef, {"population": 1000000});

// Delete the city 'LA'
var laRef = db.collection("coc("LA");
batch.delete(laRef);

// Commit the batch
batch.commit().then((_) {
  // ...
});firestore.dart
জাভা
// Get a new write batch
WriteBatch batch = db.batch();

// Set the value of 'NYC'
DocumentReference nycRef = db.collection("cities").document("NYC");
batch.set(nycRef, new City());

// Update the population of 'SF'
DocumentReference sfRef = db.collection("cities").document("SF");
batch.update(sfRef, "population", 1000000L);

// Delete the city 'LA'
DocumentReference laRef = db.collection("cities"<).do<cument(&quo>>t;LA");
batch.delete(laRef);

// asynchronously commit the batch
ApiFutureListWriteResult future = batch.commit();
// ...
// future.get() blocks on batch commit operation
for (WriteResu)) {
  System.out.println("Update time : " + result.getUpdateTime());
}ManageDataSnippets.java
পাইথন
batch = db.batch()

# Set the data for NYC
nyc_ref = db.collection("cities").document("NYC")
batch.set(nyc_ref, {"name": "New York City"})

# Update the population for SF
sf_ref = db.collection("cities").document("SF")
batch.update(sf_ref, {"population": 1000000})

# Delete DEN
den_ref = db.collection("citiesument("DEN")
batch.delete(den_ref)

# Commit the batch
batch.commit()snippets.py

Python

batch = db.batch()

# Set the data for NYC
nyc_ref = db.collection("cities").document("NYC")
batch.set(nyc_ref, {"name": "New York City"})

# Update the population for SF
sf_ref = db.collection("cities").document("SF")
batch.update(sf_ref, {"population": 1000000})

# Delete DEN
den_ref = db.collection("cities""DEN")
batch.delete(den_ref)

# Commit the batch
await batch.commit()snippets.py
সি++
// Get a new write batch
WriteBatch batch = db->batch();

// Set the value of 'NYC'
DocumentReference nyc_r>ef = db-Collection("cities").Document("NYC");
batch.Set(nyc_ref, {});

// Update the population of 'SF>'
DocumentReference sf_ref = db-Collection("citie{{"population", FieldValue::Integer(1000000)}s").Document("SF");
batch.Update(sf_ref, });>

// Delete the city 'LA'
DocumentReference la_ref = db-Collection("cities").Document("LA");
ba<tch.>&Delete(la_ref);

// Commit the batch
batch.Commit().OnCompletion([](<<const Futurevoid future)<< {
  if (future.error() == Error::kEr<<rorOk) {
    std::cout  &<<quot;Write batch success<<!"  std::endl;    std::cout  "Write batch failure: "  future.error_message()  std::endl;
  }
});snippets.cpp
নোড.জেএস
// Get a new write batch
const batch = db.batch();

// Set the value of 'NYC'
const nycRef = db.collection('cities').doc('NYC');
batch.set(nycRef, {name: 'New York City'});

// Update the population of 'SF'
const sfRef = db.collection('cities').doc('SF');
batch.update(sfRef, {population: 1000000});

// Delete the city 'LA'
const laRef = db.collection('cities').doA');
batch.delete(laRef);

// Commit the batch
await batch.commit();index.js
যান

import (
	"context"
	"log"

	"cloud.google.com/go/firestore"
)

func batchWrite(ctx context.Context, client *firestore.Client) error {
	// Get a new write batch.
	batch := client.Batch()

	// Set the value of "NYC".
	nycRef := client.Collection("cities").Doc("NYC")
	batch.Set(nycRef, map[string]interface{}{
		"name": "New York City",
	})

	// Update the population of "SF".
	sfRef := client.Collection("cities").Doc("SF")
	batch.Set(sfRef, map[string]interface{}{
		"population": 1000000,
	}, firestore.MergeAll)

	// Delete the city "LA".
	laRef := client.Collection("cities").Doc("LA")
	batch.Delete(laRef)

	// Commit the batch.
	_, err := batch.Commit(ctx)
	ie any errors in an appropriate way, such as returning them.
		log.Printf("An error has occurred: %s", err)
	}

	return err
}
save_data_batch_writes.go
পিএইচপি
$batch = $db->bulkWriter();

# Set the data for NYC
$nycRef = $db->collection('samples/php/citie>s')-document('NY>C');
$batch-set($nycRef>, [
    'name' = 'New York City'
]);

# Update the> population for SF
$sfRef = $db-c>ollection('samples/>php/cities')-document('>;SF');
$batch-update>($sfRef, [
    ['path' = 'po>pulation', 'value' = >1000000]
]);

# Delete >LA
$laRef = $db-collection('samples/php>/cities&#');
$batch-delete($laRef);

# Commit the batch
$batch-commit();data_batch_writes.php
ঐক্য
WriteBatch batch = db.StartBatch();

// Set the data for NYC
DocumentReference nycRef = db.Collection("cities").Document("NY<C");
Dict>ionarystring, object nycD<ata = new Dict>ionarystring, object
{
    { "name", "New York City" }
};
batch.Set(nycRef, nycData);

// Update the population for SF
DocumentReference sfRef = db.Collect<ion("citi>es").Document("<SF");
Dic>tionarystring, object updates = new Dictionarystring, object
{
    { "Population", 1000000}
};
batch.Update(sfRef, updates);

// Delete LA
DocumentReference laRef = db.Collection("cities").Document("LA");
batch.Delete(laRef);

// Commit the batch
batch.CommitAsync();
সি#
WriteBatch batch = db.StartBatch();

// Set the data for NYC
DocumentReference nycRef = db.Collection("cities").Document("NY<C");
Dict>ionarystring, object nycD<ata = new Dict>ionarystring, object
{
    { "name", "New York City" }
};
batch.Set(nycRef, nycData);

// Update the population for SF
DocumentReference sfRef = db.Collect<ion("citi>es").Document("<SF");
Dic>tionarystring, object updates = new Dictionarystring, object
{
    { "Population", 1000000}
};
batch.Update(sfRef, updates);

// Delete LA
DocumentReference laRef = db.Collection("cities").Docu;LA");
batch.Delete(laRef);

// Commit the batch
await batch.CommitAsync();Program.cs
রুবি
firestore.batch do |b|
  # Set the data for NYC
  b.set "#{collection_path}/NYC", { name: "New York City" }

  # Update the population for SF
  b.update "#{collection_path}/SF", { population: 1_000_000 }

  # Delete LA
  b.delet;
endtransactions_and_batched_writes.rb

ট্রানজ্যাকশনের মতোই, ব্যাচড রাইটও অ্যাটমিক। ট্রানজ্যাকশনের বিপরীতে, ব্যাচড রাইটের ক্ষেত্রে পঠিত ডকুমেন্টগুলো অপরিবর্তিত আছে কিনা তা নিশ্চিত করার প্রয়োজন হয় না, যার ফলে ব্যর্থতার ঘটনা কম ঘটে। এগুলোতে রিট্রাই বা অতিরিক্ত রিট্রাইয়ের কারণে ব্যর্থতার কোনো সম্ভাবনা থাকে না। ব্যবহারকারীর ডিভাইস অফলাইনে থাকলেও ব্যাচড রাইট সম্পাদিত হয়।

শত শত ডকুমেন্ট একসাথে ব্যাচ আকারে লেখার জন্য অনেক ইনডেক্স আপডেটের প্রয়োজন হতে পারে এবং এটি ট্রানজ্যাকশন সাইজের সীমা অতিক্রম করতে পারে। এক্ষেত্রে, প্রতি ব্যাচে ডকুমেন্টের সংখ্যা কমিয়ে দিন। বিপুল সংখ্যক ডকুমেন্ট লেখার জন্য, এর পরিবর্তে বাল্ক রাইটার বা সমান্তরালভাবে পৃথক পৃথক রাইট ব্যবহার করার কথা বিবেচনা করুন।

পারমাণবিক ক্রিয়াকলাপের জন্য ডেটা যাচাইকরণ

মোবাইল/ওয়েব ক্লায়েন্ট লাইব্রেরির জন্য, আপনি Cloud Firestore Security Rules ব্যবহার করে ডেটা ভ্যালিডেট করতে পারেন। আপনি নিশ্চিত করতে পারেন যে সম্পর্কিত ডকুমেন্টগুলো সর্বদা অ্যাটমিকভাবে এবং একটি ট্রানজ্যাকশন বা ব্যাচড রাইটের অংশ হিসেবে আপডেট হয়। এক সেট অপারেশন সম্পন্ন হওয়ার পরে কিন্তু Cloud Firestore অপারেশনগুলো কমিট করার আগে , কোনো ডকুমেন্টের অবস্থা অ্যাক্সেস ও ভ্যালিডেট করতে getAfter() সিকিউরিটি রুল ফাংশনটি ব্যবহার করুন।

উদাহরণস্বরূপ, কল্পনা করুন যে cities উদাহরণের ডাটাবেসে একটি countries কালেকশনও রয়েছে। প্রতিটি country ডকুমেন্টে একটি last_updated ফিল্ড ব্যবহার করা হয়, যা সেই দেশের সাথে সম্পর্কিত কোনো শহর শেষবার কখন আপডেট করা হয়েছিল তার হিসাব রাখে। নিম্নলিখিত নিরাপত্তা নিয়মগুলো অনুযায়ী, একটি city ডকুমেন্ট আপডেট করা হলে, সংশ্লিষ্ট দেশের last_updated ফিল্ডটিও অ্যাটমিকভাবে আপডেট হতে হবে:

service cloud.firestore {
  match /databases/{database}/documents {
    // If you update a city doc, you must also
    // update the related country's last_updated field.
    match /cities/{city} {
      allow write: if request.auth != null &&
        getAfter(
          /databases/$(database)/documents/countries/$(request.resource.data.country)
        ).data.last_updated == request.time;
    }

    match /countries/{country} {
      allow write: if request.auth != null;
    }
  }
}

নিরাপত্তা নিয়মের সীমাবদ্ধতা

ট্রানজ্যাকশন বা ব্যাচড রাইটের নিরাপত্তা নিয়মে, ব্যাচের প্রতিটি একক ডকুমেন্ট অপারেশনের জন্য স্বাভাবিক ১০টি কল সীমার পাশাপাশি, সম্পূর্ণ অ্যাটমিক অপারেশনের জন্য ২০টি ডকুমেন্ট অ্যাক্সেস কলের একটি সীমা রয়েছে।

উদাহরণস্বরূপ, একটি চ্যাট অ্যাপ্লিকেশনের জন্য নিম্নলিখিত নিয়মগুলো বিবেচনা করুন:

service cloud.firestore {
  match /databases/{db}/documents {
    function prefix() {
      return /databases/{db}/documents;
    }
    match /chatroom/{roomId} {
      allow read, write: if request.auth != null && roomId in get(/$(prefix())/users/$(request.auth.uid)).data.chats
                            || exists(/$(prefix())/admins/$(request.auth.uid));
    }
    match /users/{userId} {
      allow read, write: if request.auth != null && request.auth.uid == userId
                            || exists(/$(prefix())/admins/$(request.auth.uid));
    }
    match /admins/{userId} {
      allow read, write: if request.auth != null && exists(/$(prefix())/admins/$(request.auth.uid));
    }
  }
}

নিচের কোড স্নিপেটগুলো কয়েকটি ডেটা অ্যাক্সেস প্যাটার্নের জন্য ব্যবহৃত ডকুমেন্ট অ্যাক্সেস কলের সংখ্যা তুলে ধরেছে:

// 0 document access calls used, because the rules evaluation short-circuits
// before the exists() call is invoked.
db.collection('user').doc('myuid').get(...);

// 1 document access call used. The maximum total allowed for this call
// is 10, because it is a single document request.
db.collection('chatroom').doc('mygroup').get(...);

// Initializing a write batch...
var batch = db.batch();

// 2 document access calls used, 10 allowed.
var group1Ref = db.collection("chatroom").doc("group1");
batch.set(group1Ref, {msg: "Hello, from Admin!"});

// 1 document access call used, 10 allowed.
var newUserRef = db.collection("users").doc("newuser");
batch.update(newUserRef, {"lastSignedIn": new Date()});

// 1 document access call used, 10 allowed.
var removedAdminRef = db.collection("admin").doc("otheruser");
batch.delete(removedAdminRef);

// The batch used a total of 2 + 1 + 1 = 4 document access calls, out of a total
// 20 allowed.
batch.commit();

বড় আকারের রাইট ও ব্যাচড রাইটের কারণে সৃষ্ট ল্যাটেন্সি সমস্যা, ওভারল্যাপিং ট্রানজ্যাকশনের দ্বন্দ্বজনিত ত্রুটি এবং অন্যান্য সমস্যা সমাধানের উপায় সম্পর্কে আরও তথ্যের জন্য ট্রাবলশুটিং পেজটি দেখে নিতে পারেন।