class Google::Cloud::Firestore::Batch

# Batch

A batch in Cloud Firestore is a set of writes that execute atomically at a single logical point in time in a database.

All changes are accumulated in memory until the block passed to {Client#batch} completes. Unlike transactions, batches don't lock on document reads, should only fail if users provide preconditions, and are not automatically retried.

@see firebase.google.com/docs/firestore/manage-data/transactions

Transactions and Batched Writes

@example

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

firestore.batch do |b|
  # Set the data for NYC
  b.set("cities/NYC", { name: "New York City" })

  # Update the population for SF
  b.update("cities/SF", { population: 1000000 })

  # Delete LA
  b.delete("cities/LA")
end

Public Class Methods

from_client(client) click to toggle source

@private New Batch reference object from a path.

# File lib/google/cloud/firestore/batch.rb, line 415
def self.from_client client
  new.tap do |b|
    b.instance_variable_set :@client, client
  end
end
new() click to toggle source

@private New Batch object.

# File lib/google/cloud/firestore/batch.rb, line 59
def initialize
  @writes = []
end

Public Instance Methods

client()
Alias for: firestore
closed?() click to toggle source

@private the batch is complete and closed

# File lib/google/cloud/firestore/batch.rb, line 409
def closed?
  @closed
end
commit() click to toggle source

@private commit the batch

# File lib/google/cloud/firestore/batch.rb, line 398
def commit
  ensure_not_closed!
  @closed = true
  return nil if @writes.empty?
  resp = service.commit @writes.flatten
  return nil if resp.nil?
  CommitResponse.from_grpc resp, @writes
end
create(doc, data) click to toggle source

Create a document with the provided data (fields and values).

The batch will fail if the document already exists.

@param [String, DocumentReference] doc A string representing the

path of the document, or a document reference object.

@param [Hash] data The document's fields and values.

@example Create a document using a document path:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

firestore.batch do |b|
  b.create("cities/NYC", { name: "New York City" })
end

@example Create a document using a document reference:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

# Get a document reference
nyc_ref = firestore.doc "cities/NYC"

firestore.batch do |b|
  b.create(nyc_ref, { name: "New York City" })
end

@example Create a document and set a field to server_time:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

# Get a document reference
nyc_ref = firestore.doc "cities/NYC"

firestore.batch do |b|
  b.create(nyc_ref, { name: "New York City",
                      updated_at: firestore.field_server_time })
end
# File lib/google/cloud/firestore/batch.rb, line 117
def create doc, data
  ensure_not_closed!

  doc_path = coalesce_doc_path_argument doc

  @writes << Convert.write_for_create(doc_path, data)

  nil
end
delete(doc, exists: nil, update_time: nil) click to toggle source

Deletes a document from the database.

@param [String, DocumentReference] doc A string representing the

path of the document, or a document reference object.

@param [Boolean] exists Whether the document must exist. When `true`,

the document must exist or an error is raised. Default is `false`.
Optional.

@param [Time] update_time When set, the document must have been last

updated at that time. Optional.

@example Delete a document using a document path:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

firestore.batch do |b|
  b.delete "cities/NYC"
end

@example Delete a document using a document reference:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

# Get a document reference
nyc_ref = firestore.doc "cities/NYC"

firestore.batch do |b|
  b.delete nyc_ref
end

@example Delete a document using `exists`:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

firestore.batch do |b|
  b.delete "cities/NYC", exists: true
end

@example Delete a document using the `update_time` precondition:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

last_updated_at = Time.now - 42 # 42 seconds ago

firestore.batch do |b|
  b.delete "cities/NYC", update_time: last_updated_at
end
# File lib/google/cloud/firestore/batch.rb, line 382
def delete doc, exists: nil, update_time: nil
  ensure_not_closed!

  doc_path = coalesce_doc_path_argument doc

  @writes << Convert.write_for_delete(
    doc_path, exists: exists, update_time: update_time
  )

  nil
end
firestore() click to toggle source

The client the Cloud Firestore batch belongs to.

@return [Client] firestore client.

# File lib/google/cloud/firestore/batch.rb, line 67
def firestore
  @client
end
Also aliased as: client
service() click to toggle source

@private The Service object.

# File lib/google/cloud/firestore/batch.rb, line 423
def service
  ensure_client!

  firestore.service
end
set(doc, data, merge: nil) click to toggle source

Write the provided data (fields and values) to the provided document. If the document does not exist, it will be created. By default, the provided data overwrites existing data, but the provided data can be merged into the existing document using the `merge` argument.

If you're not sure whether the document exists, use the `merge` argument to merge the new data with any existing document data to avoid overwriting entire documents.

@param [String, DocumentReference] doc A string representing the

path of the document, or a document reference object.

@param [Hash] data The document's fields and values. @param [Boolean, FieldPath, String, Symbol] merge When

`true`, all provided data is merged with the existing document data.
When the argument is one or more field path, only the data for
fields in this argument is merged with the existing document data.
The default is to not merge, but to instead overwrite the existing
document data.

@example Set a document using a document path:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

firestore.batch do |b|
  b.set("cities/NYC", { name: "New York City" })
end

@example Create a document using a document reference:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

# Get a document reference
nyc_ref = firestore.doc "cities/NYC"

firestore.batch do |b|
  b.set(nyc_ref, { name: "New York City" })
end

@example Set a document and merge all data:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

firestore.batch do |b|
  b.set("cities/NYC", { name: "New York City" }, merge: true)
end

@example Set a document and merge only name:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

firestore.batch do |b|
  b.set("cities/NYC", { name: "New York City" }, merge: :name)
end

@example Set a document and deleting a field using merge:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

# Get a document reference
nyc_ref = firestore.doc "cities/NYC"

nyc_data = { name: "New York City",
             trash: firestore.field_delete }

firestore.batch do |b|
  b.set(nyc_ref, nyc_data, merge: true)
end

@example Set a document and set a field to server_time:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

# Get a document reference
nyc_ref = firestore.doc "cities/NYC"

nyc_data = { name: "New York City",
             updated_at: firestore.field_server_time }

firestore.batch do |b|
  b.set(nyc_ref, nyc_data, merge: true)
end
# File lib/google/cloud/firestore/batch.rb, line 216
def set doc, data, merge: nil
  ensure_not_closed!

  doc_path = coalesce_doc_path_argument doc

  @writes << Convert.write_for_set(doc_path, data, merge: merge)

  nil
end
update(doc, data, update_time: nil) click to toggle source

Update the document with the provided data (fields and values). The provided data is merged into the existing document data.

The batch will fail if the document does not exist.

@param [String, DocumentReference] doc A string representing the

path of the document, or a document reference object.

@param [Hash<FieldPath|String|Symbol, Object>] data The document's

fields and values.

The top-level keys in the data hash are considered field paths, and
can either be a FieldPath object, or a string representing the
nested fields. In other words the string represents individual
fields joined by ".". Fields containing `~`, `*`, `/`, `[`, `]`, and
`.` cannot be in a dotted string, and should provided using a
{FieldPath} object instead.

@param [Time] update_time When set, the document must have been last

updated at that time. Optional.

@example Update a document using a document path:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

firestore.batch do |b|
  b.update("cities/NYC", { name: "New York City" })
end

@example Directly update a deeply-nested field with a `FieldPath`:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

nested_field_path = firestore.field_path :favorites, :food

firestore.batch do |b|
  b.update("users/frank", { nested_field_path => "Pasta" })
end

@example Update a document using a document reference:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

# Get a document reference
nyc_ref = firestore.doc "cities/NYC"

firestore.batch do |b|
  b.update(nyc_ref, { name: "New York City" })
end

@example Update a document using the `update_time` precondition:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

last_updated_at = Time.now - 42 # 42 seconds ago

firestore.batch do |b|
  b.update("cities/NYC", { name: "New York City" },
           update_time: last_updated_at)
end

@example Update a document and deleting a field:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

# Get a document reference
nyc_ref = firestore.doc "cities/NYC"

nyc_data = { name: "New York City",
             trash: firestore.field_delete }

firestore.batch do |b|
  b.update(nyc_ref, nyc_data)
end

@example Update a document and set a field to server_time:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

# Get a document reference
nyc_ref = firestore.doc "cities/NYC"

nyc_data = { name: "New York City",
             updated_at: firestore.field_server_time }

firestore.batch do |b|
  b.update(nyc_ref, nyc_data)
end
# File lib/google/cloud/firestore/batch.rb, line 320
def update doc, data, update_time: nil
  ensure_not_closed!

  doc_path = coalesce_doc_path_argument doc

  @writes << Convert.write_for_update(doc_path, data, update_time: update_time)

  nil
end

Protected Instance Methods

coalesce_doc_path_argument(doc_path) click to toggle source

@private

# File lib/google/cloud/firestore/batch.rb, line 433
def coalesce_doc_path_argument doc_path
  return doc_path.path if doc_path.respond_to? :path

  client.doc(doc_path).path
end
ensure_client!() click to toggle source

@private Raise an error unless an database available.

# File lib/google/cloud/firestore/batch.rb, line 447
def ensure_client!
  raise "Must have active connection to service" unless firestore
end
ensure_not_closed!() click to toggle source

@private

# File lib/google/cloud/firestore/batch.rb, line 441
def ensure_not_closed!
  raise "batch is closed" if closed?
end
ensure_service!() click to toggle source

@private Raise an error unless an active connection to the service is available.

# File lib/google/cloud/firestore/batch.rb, line 454
def ensure_service!
  raise "Must have active connection to service" unless service
end