Class: Google::Cloud::Firestore::Transaction

Inherits:
Object
  • Object
show all
Defined in:
lib/google/cloud/firestore/transaction.rb

Overview

Transaction

A transaction in Cloud Firestore is a set of reads and writes that execute atomically at a single logical point in time.

All changes are accumulated in memory until the block passed to Client#transaction completes. Transactions will be automatically retried when documents change before the transaction is committed. See Client#transaction.

Examples:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

city = firestore.col("cities").doc("SF")
city.set({ name: "San Francisco",
           state: "CA",
           country: "USA",
           capital: false,
           population: 860000 })

firestore.transaction do |tx|
  new_population = tx.get(city).data[:population] + 1
  tx.update(city, { population: new_population })
end

Access collapse

Modifications collapse

Instance Method Summary collapse

Instance Method Details

#create(doc, data) ⇒ Object

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

The operation will fail if the document already exists.

Examples:

Create a document using a document path:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

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

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.transaction do |tx|
  tx.create(nyc_ref, { name: "New York City" })
end

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.transaction do |tx|
  tx.create(nyc_ref, { name: "New York City",
                       updated_at: firestore.field_server_time })
end

Parameters:

  • doc (String, DocumentReference)

    A string representing the path of the document, or a document reference object.

  • data (Hash)

    The document's fields and values.



364
365
366
367
368
369
370
371
372
# File 'lib/google/cloud/firestore/transaction.rb', line 364

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) ⇒ Object

Deletes a document from the database.

Examples:

Delete a document using a document path:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

firestore.transaction do |tx|
  # Delete a document
  tx.delete "cities/NYC"
end

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.transaction do |tx|
  # Delete a document
  tx.delete nyc_ref
end

Delete a document using exists:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

firestore.transaction do |tx|
  # Delete a document
  tx.delete "cities/NYC", exists: true
end

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.transaction do |tx|
  # Delete a document
  tx.delete "cities/NYC", update_time: last_updated_at
end

Parameters:

  • doc (String, DocumentReference)

    A string representing the path of the document, or a document reference object.

  • exists (Boolean) (defaults to: nil)

    Whether the document must exist. When true, the document must exist or an error is raised. Default is false. Optional.

  • update_time (Time) (defaults to: nil)

    When set, the document must have been last updated at that time. Optional.



636
637
638
639
640
641
642
643
644
645
646
# File 'lib/google/cloud/firestore/transaction.rb', line 636

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

#firestoreClient Also known as: client

The client the Cloud Firestore transaction belongs to.

Returns:

  • (Client)

    firestore client.



74
75
76
# File 'lib/google/cloud/firestore/transaction.rb', line 74

def firestore
  @client
end

#get(obj) {|documents| ... } ⇒ DocumentSnapshot, Enumerator<DocumentSnapshot> Also known as: run

Retrieves document snapshots for the given value. Valid values can be a string representing either a document or a collection of documents, a document reference object, a collection reference object, or a query to be run.

Examples:

Get a document snapshot given a document path:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

firestore.transaction do |tx|
  # Get a document snapshot
  nyc_snap = tx.get "cities/NYC"
end

Get a document snapshot given a document reference:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

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

firestore.transaction do |tx|
  # Get a document snapshot
  nyc_snap = tx.get nyc_ref
end

Get document snapshots given a collection path:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

firestore.transaction do |tx|
  # Get documents for a collection path
  tx.get("cities").each do |city|
    # Update the city population by 1
    tx.update(city, { population: city[:population] + 1})
  end
end

Get document snapshots given a collection reference:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

# Get a collection reference
cities_col = firestore.col :cities

firestore.transaction do |tx|
  # Get documents for a collection
  tx.get(cities_col).each do |city|
    # Update the city population by 1
    tx.update(city, { population: city[:population] + 1})
  end
end

Get document snapshots given a query:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

# Create a query
query = firestore.col(:cities).select(:population)

firestore.transaction do |tx|
  # Get/run a query
  tx.get(query).each do |city|
    # Update the city population by 1
    tx.update(city, { population: city[:population] + 1})
  end
end

Parameters:

Yields:

  • (documents)

    The block for accessing the document snapshots.

Yield Parameters:

Returns:

  • (DocumentSnapshot, Enumerator<DocumentSnapshot>)

    A single document snapshot when passed a document path or a document reference object, or a list of document snapshots when passed other valid values.



248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/google/cloud/firestore/transaction.rb', line 248

def get obj
  ensure_not_closed!
  ensure_service!

  obj = coalesce_get_argument obj

  if obj.is_a? DocumentReference
    doc = get_all([obj]).first
    yield doc if block_given?
    return doc
  end

  return enum_for :get, obj unless block_given?

  results = service.run_query obj.parent_path, obj.query,
                              transaction: transaction_or_create
  results.each do |result|
    extract_transaction_from_result! result
    next if result.document.nil?
    yield DocumentSnapshot.from_query_result result, client
  end
end

#get_aggregate(aggregate_query) {|documents| ... } ⇒ Object

Retrieves aggregate query snapshots for the given value. Valid values can be a string representing either a document or a collection of documents, a document reference object, a collection reference object, or a query to be run.

Examples:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

query = firestore.col "cities"

# Create an aggregate query
aq = query.aggregate_query
          .add_count

firestore.transaction do |tx|
  tx.get_aggregate aq do |aggregate_snapshot|
    puts aggregate_snapshot.get
  end
end

Parameters:

Yields:

  • (documents)

    The block for accessing the aggregate query snapshot.

Yield Parameters:



301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
# File 'lib/google/cloud/firestore/transaction.rb', line 301

def get_aggregate aggregate_query
  ensure_not_closed!
  ensure_service!

  return enum_for :get_aggregate, aggregate_query unless block_given?

  results = service.run_aggregate_query aggregate_query.parent_path,
                                        aggregate_query.structured_aggregation_query,
                                        transaction: transaction_or_create
  results.each do |result|
    extract_transaction_from_result! result
    next if result.result.nil?
    yield AggregateQuerySnapshot.from_run_aggregate_query_response result
  end
end

#get_all(*docs, field_mask: nil) {|documents| ... } ⇒ Enumerator<DocumentSnapshot> Also known as: get_docs, get_documents, find

Retrieves a list of document snapshots.

Examples:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

firestore.transaction do |tx|
  # Get and print city documents
  tx.get_all("cities/NYC", "cities/SF", "cities/LA").each do |city|
    puts "#{city.document_id} has #{city[:population]} residents."
  end
end

Get docs using a field mask:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

firestore.transaction do |tx|
  # Get and print city documents
  cities = ["cities/NYC", "cities/SF", "cities/LA"]
  tx.get_all(*cities, field_mask: :population).each do |city|
    puts "#{city.document_id} has #{city[:population]} residents."
  end
end

Parameters:

  • docs (String, DocumentReference, Array<String|DocumentReference>)

    One or more strings representing the path of the document, or document reference objects.

  • field_mask (Array<String|FieldPath>) (defaults to: nil)

    One or more field path values, representing the fields of the document to be returned. If a document has a field that is not present in this mask, that field will not be returned in the response. All fields are returned when the mask is not set.

    A field path can either be a FieldPath object, or a dotted 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. See Client#field_path.)

Yields:

  • (documents)

    The block for accessing the document snapshots.

Yield Parameters:

Returns:



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/google/cloud/firestore/transaction.rb', line 129

def get_all *docs, field_mask: nil
  ensure_not_closed!
  ensure_service!

  unless block_given?
    return enum_for :get_all, *docs, field_mask: field_mask
  end

  doc_paths = Array(docs).flatten.map do |doc_path|
    coalesce_doc_path_argument doc_path
  end
  mask = Array(field_mask).map do |field_path|
    if field_path.is_a? FieldPath
      field_path.formatted_string
    else
      FieldPath.parse(field_path).formatted_string
    end
  end
  mask = nil if mask.empty?

  results = service.get_documents \
    doc_paths, mask: mask, transaction: transaction_or_create
  results.each do |result|
    extract_transaction_from_result! result
    next if result.result.nil?
    yield DocumentSnapshot.from_batch_result result, client
  end
end

#set(doc, data, merge: nil) ⇒ Object

Writes 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.

Examples:

Set a document using a document path:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

firestore.transaction do |tx|
  # Update a document
  tx.set("cities/NYC", { name: "New York City" })
end

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.transaction do |tx|
  # Update a document
  tx.set(nyc_ref, { name: "New York City" })
end

Set a document and merge all data:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

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

Set a document and merge only name:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

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

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.transaction do |tx|
  tx.set(nyc_ref, nyc_data, merge: true)
end

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.transaction do |tx|
  tx.set(nyc_ref, nyc_data, merge: true)
end

Parameters:

  • doc (String, DocumentReference)

    A string representing the path of the document, or a document reference object.

  • data (Hash)

    The document's fields and values.

  • merge (Boolean, FieldPath, String, Symbol) (defaults to: nil)

    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.



465
466
467
468
469
470
471
472
473
# File 'lib/google/cloud/firestore/transaction.rb', line 465

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

#transaction_idString

The transaction identifier.

Returns:

  • (String)

    transaction identifier.



66
67
68
# File 'lib/google/cloud/firestore/transaction.rb', line 66

def transaction_id
  @transaction_id
end

#update(doc, data, update_time: nil) ⇒ Object

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

The operation will fail if the document does not exist.

Examples:

Update a document using a document path:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

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

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.transaction do |tx|
  tx.update("users/frank", { nested_field_path => "Pasta" })
end

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.transaction do |tx|
  tx.update(nyc_ref, { name: "New York City" })
end

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.transaction do |tx|
  tx.update("cities/NYC", { name: "New York City" },
           update_time: last_updated_at)
end

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.transaction do |tx|
  tx.update(nyc_ref, nyc_data)
end

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.transaction do |tx|
  tx.update(nyc_ref, nyc_data)
end

Parameters:

  • doc (String, DocumentReference)

    A string representing the path of the document, or a document reference object.

  • data (Hash<FieldPath|String|Symbol, Object>)

    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.

  • update_time (Time) (defaults to: nil)

    When set, the document must have been last updated at that time. Optional.



569
570
571
572
573
574
575
576
577
578
# File 'lib/google/cloud/firestore/transaction.rb', line 569

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