Class: Google::Cloud::Firestore::Client

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

Overview

Client

The Cloud Firestore Client used is to access and manipulate the collections and documents in the Firestore database.

Examples:

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

Access collapse

Operations collapse

Instance Method Summary collapse

Instance Method Details

#batch {|batch| ... } ⇒ CommitResponse

Perform multiple changes at the same time.

All changes are accumulated in memory until the block completes. Unlike transactions, batches don't lock on document reads, should only fail if users provide preconditions, and are not automatically retried. See Batch.

Examples:

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

Yields:

  • (batch)

    The block for reading data and making changes.

Yield Parameters:

  • batch (Batch)

    The write batch object for making changes.

Returns:

See Also:



651
652
653
654
655
# File 'lib/google/cloud/firestore/client.rb', line 651

def batch
  batch = Batch.from_client self
  yield batch
  batch.commit
end

#col(collection_path) ⇒ CollectionReference Also known as: collection

Retrieves a collection.

Examples:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

# Get the cities collection
cities_col = firestore.col "cities"

# Get the document for NYC
nyc_ref = cities_col.doc "NYC"

Parameters:

  • collection_path (String)

    A string representing the path of the collection, relative to the document root of the database.

Returns:



148
149
150
151
152
153
154
# File 'lib/google/cloud/firestore/client.rb', line 148

def col collection_path
  if collection_path.to_s.split("/").count.even?
    raise ArgumentError, "collection_path must refer to a collection."
  end

  CollectionReference.from_path "#{path}/documents/#{collection_path}", self
end

#col_group(collection_id) ⇒ CollectionGroup Also known as: collection_group

Creates and returns a new collection group that includes all documents in the database that are contained in a collection or subcollection with the given collection_id.

Examples:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

# Get the cities collection group query
col_group = firestore.col_group "cities"

col_group.get do |city|
  puts "#{city.document_id} has #{city[:population]} residents."
end

Parameters:

  • collection_id (String)

    Identifies the collections to query over. Every collection or subcollection with this ID as the last segment of its path will be included. Cannot contain a slash (/).

Returns:



180
181
182
183
184
185
186
# File 'lib/google/cloud/firestore/client.rb', line 180

def col_group collection_id
  if collection_id.include? "/"
    raise ArgumentError, "Invalid collection_id: '#{collection_id}', must not contain '/'."
  end

  CollectionGroup.from_collection_id service.documents_path, collection_id, self
end

#cols(read_time: nil) {|collections| ... } ⇒ Enumerator<CollectionReference> Also known as: collections, list_collections

Retrieves an enumerator for the root collections.

Examples:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

# Get the root collections
firestore.cols.each do |col|
  puts col.collection_id
end
require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new
read_time = Time.now

# Get the root collections
firestore.cols(read_time: read_time).each do |col|
  puts col.collection_id
end

Parameters:

  • read_time (Time) (defaults to: nil)

    Reads documents as they were at the given time. This may not be older than 270 seconds. Optional

Yields:

  • (collections)

    The block for accessing the collections.

Yield Parameters:

Returns:

  • (Enumerator<CollectionReference>)

    An enumerator of collection references. If a block is provided, this is the same enumerator that is accessed through the block.



119
120
121
122
123
124
125
# File 'lib/google/cloud/firestore/client.rb', line 119

def cols read_time: nil, &block
  ensure_service!
  grpc = service.list_collections "#{path}/documents", read_time: read_time
  cols_enum = CollectionReferenceList.from_grpc(grpc, self, "#{path}/documents", read_time: read_time).all
  cols_enum.each(&block) if block_given?
  cols_enum
end

#database_idString

The database identifier for the Cloud Firestore database.

Returns:

  • (String)

    database identifier.



72
73
74
# File 'lib/google/cloud/firestore/client.rb', line 72

def database_id
  service.database
end

#doc(document_path) ⇒ DocumentReference Also known as: document

Retrieves a document reference.

Examples:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

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

puts nyc_ref.document_id

Parameters:

  • document_path (String)

    A string representing the path of the document, relative to the document root of the database.

Returns:



257
258
259
260
261
262
263
264
265
# File 'lib/google/cloud/firestore/client.rb', line 257

def doc document_path
  if document_path.to_s.split("/").count.odd?
    raise ArgumentError, "document_path must refer to a document."
  end

  doc_path = "#{path}/documents/#{document_path}"

  DocumentReference.from_path doc_path, self
end

#document_idFieldPath

Creates a field path object representing the sentinel ID of a document. It can be used in queries to sort or filter by the document ID. See FieldPath.document_id.

Examples:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

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

# Create a query
query = cities_col.order(firestore.document_id)
                  .start_at("NYC")

query.get do |city|
  puts "#{city.document_id} has #{city[:population]} residents."
end

Returns:



380
381
382
# File 'lib/google/cloud/firestore/client.rb', line 380

def document_id
  FieldPath.document_id
end

#field_array_delete(*values) ⇒ FieldValue

Creates a sentinel value to indicate the removal of the given values with an array.

Examples:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

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

array_delete = firestore.field_array_delete 7, 8, 9

nyc_ref.update({ name: "New York City",
                 lucky_numbers: array_delete })

Parameters:

  • values (Object)

    The values to remove from the array. Required.

Returns:

  • (FieldValue)

    The array delete field value object.



496
497
498
# File 'lib/google/cloud/firestore/client.rb', line 496

def field_array_delete *values
  FieldValue.array_delete(*values)
end

#field_array_union(*values) ⇒ FieldValue

Creates a sentinel value to indicate the union of the given values with an array.

Examples:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

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

array_union = firestore.field_array_union 1, 2, 3

nyc_ref.update({ name: "New York City",
                 lucky_numbers: array_union })

Parameters:

  • values (Object)

    The values to add to the array. Required.

Returns:

  • (FieldValue)

    The array union field value object.



471
472
473
# File 'lib/google/cloud/firestore/client.rb', line 471

def field_array_union *values
  FieldValue.array_union(*values)
end

#field_deleteFieldValue

Creates a field value object representing the deletion of a field in document data.

Examples:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

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

nyc_ref.update({ name: "New York City",
                 trash: firestore.field_delete })

Returns:



425
426
427
# File 'lib/google/cloud/firestore/client.rb', line 425

def field_delete
  FieldValue.delete
end

#field_increment(value) ⇒ FieldValue

Creates a sentinel value to indicate the addition the given value to the field's current value.

If the field's current value is not an integer or a double value (Numeric), or if the field does not yet exist, the transformation will set the field to the given value. If either of the given value or the current field value are doubles, both values will be interpreted as doubles. Double arithmetic and representation of double values follow IEEE 754 semantics. If there is positive/negative integer overflow, the field is resolved to the largest magnitude positive/negative integer.

Examples:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

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

# Set the population to increment by 1.
increment_value = firestore.field_increment 1

nyc_ref.update({ name: "New York City",
                 population: increment_value })

Parameters:

  • value (Numeric)

    The value to add to the given value. Required.

Returns:

  • (FieldValue)

    The increment field value object.

Raises:

  • (ArgumentError)

    if the value is not a Numeric.



533
534
535
# File 'lib/google/cloud/firestore/client.rb', line 533

def field_increment value
  FieldValue.increment value
end

#field_maximum(value) ⇒ FieldValue

Creates a sentinel value to indicate the setting the field to the maximum of its current value and the given value.

If the field is not an integer or double (Numeric), or if the field does not yet exist, the transformation will set the field to the given value. If a maximum operation is applied where the field and the input value are of mixed types (that is - one is an integer and one is a double) the field takes on the type of the larger operand. If the operands are equivalent (e.g. 3 and 3.0), the field does not change. 0, 0.0, and -0.0 are all zero. The maximum of a zero stored value and zero input value is always the stored value. The maximum of any numeric value x and NaN is NaN.

Examples:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

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

# Set the population to be at maximum 4,000,000.
maximum_value = firestore.field_maximum 4000000

nyc_ref.update({ name: "New York City",
                 population: maximum_value })

Parameters:

  • value (Numeric)

    The value to compare against the given value to calculate the maximum value to set. Required.

Returns:

  • (FieldValue)

    The maximum field value object.

Raises:

  • (ArgumentError)

    if the value is not a Numeric.



572
573
574
# File 'lib/google/cloud/firestore/client.rb', line 572

def field_maximum value
  FieldValue.maximum value
end

#field_minimum(value) ⇒ FieldValue

Creates a sentinel value to indicate the setting the field to the minimum of its current value and the given value.

If the field is not an integer or double (Numeric), or if the field does not yet exist, the transformation will set the field to the input value. If a minimum operation is applied where the field and the input value are of mixed types (that is - one is an integer and one is a double) the field takes on the type of the smaller operand. If the operands are equivalent (e.g. 3 and 3.0), the field does not change. 0, 0.0, and -0.0 are all zero. The minimum of a zero stored value and zero input value is always the stored value. The minimum of any numeric value x and NaN is NaN.

Examples:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

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

# Set the population to be at minimum 1,000,000.
minimum_value = firestore.field_minimum 1000000

nyc_ref.update({ name: "New York City",
                 population: minimum_value })

Parameters:

  • value (Numeric)

    The value to compare against the given value to calculate the minimum value to set. Required.

Returns:

  • (FieldValue)

    The minimum field value object.

Raises:

  • (ArgumentError)

    if the value is not a Numeric.



611
612
613
# File 'lib/google/cloud/firestore/client.rb', line 611

def field_minimum value
  FieldValue.minimum value
end

#field_path(*fields) ⇒ FieldPath

Creates a field path object representing a nested field for document data.

Examples:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

user_snap = firestore.doc("users/frank").get

nested_field_path = firestore.field_path :favorites, :food
user_snap.get(nested_field_path) #=> "Pizza"

Parameters:

  • fields (String, Symbol, Array<String|Symbol>)

    One or more strings representing the path of the data to select. Each field must be provided separately.

Returns:



404
405
406
# File 'lib/google/cloud/firestore/client.rb', line 404

def field_path *fields
  FieldPath.new(*fields)
end

#field_server_timeFieldValue

Creates a field value object representing set a field's value to the server timestamp when accessing the document data.

Examples:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

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

nyc_ref.update({ name: "New York City",
                 updated_at: firestore.field_server_time })

Returns:

  • (FieldValue)

    The server time field value object.



446
447
448
# File 'lib/google/cloud/firestore/client.rb', line 446

def field_server_time
  FieldValue.server_time
end

#filter(field, operator, value) ⇒ Google::Cloud::Firestore::Filter

Creates a filter object.

Examples:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

# Create a filter
filter = firestore.filter(:population, :>=, 1000000)

Parameters:

  • field (FieldPath, String, Symbol)

    A field path to filter results with. If a FieldPath object is not provided then the field will be treated as a dotted string, meaning the string represents individual fields joined by ".". Fields containing ~, *, /, [, ], and . cannot be in a dotted string, and should provided using a FieldPath object instead.

  • operator (String, Symbol)

    The operation to compare the field to. Acceptable values include:

    • less than: <, lt
    • less than or equal: <=, lte
    • greater than: >, gt
    • greater than or equal: >=, gte
    • equal: =, ==, eq, eql, is
    • not equal: !=
    • in: in
    • not in: not-in, not_in
    • array contains: array-contains, array_contains
  • value (Object)

    The value to compare the property to. Defaults to nil. Possible values are:

    • Integer
    • Float/BigDecimal
    • String
    • Boolean
    • Array
    • Date/Time
    • StringIO
    • Google::Cloud::Datastore::Key
    • Google::Cloud::Datastore::Entity
    • nil

Returns:



235
236
237
# File 'lib/google/cloud/firestore/client.rb', line 235

def filter field, operator, value
  Filter.new field, operator, value
end

#get_all(*docs, field_mask: nil, read_time: 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

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

Get docs using a field mask:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

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

Get docs using a read_time:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

read_time = Time.now

# Get and print city documents
cities = ["cities/NYC", "cities/SF", "cities/LA"]
firestore.get_all(cities, read_time: read_time).each do |city|
  puts "#{city.document_id} has #{city[:population]} residents."
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 #field_path.)

  • read_time (Time) (defaults to: nil)

    Reads documents as they were at the given time. This may not be older than 270 seconds. Optional

Yields:

  • (documents)

    The block for accessing the document snapshots.

Yield Parameters:

Returns:



328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
# File 'lib/google/cloud/firestore/client.rb', line 328

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

  unless block_given?
    return enum_for :get_all, *docs, field_mask: field_mask, read_time: read_time
  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, read_time: read_time
  results.each do |result|
    next if result.result.nil?
    yield DocumentSnapshot.from_batch_result result, self
  end
end

#project_idString

The project identifier for the Cloud Firestore database.

Returns:

  • (String)

    project identifier.



64
65
66
# File 'lib/google/cloud/firestore/client.rb', line 64

def project_id
  service.project
end

#read_only_transaction(read_time: nil) {|transaction| ... } ⇒ Object

Create a transaction to perform multiple reads that are executed atomically at a single logical point in time in a database.

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

Examples:

Read only transaction with read time

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

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

read_time = Time.now

firestore.read_only_transaction(read_time: read_time) do |tx|
  # Get a document snapshot
  nyc_snap = tx.get nyc_ref
end

Parameters:

  • read_time (Time) (defaults to: nil)

    The maximum number of retries for transactions failed due to errors. Default is 5. Optional.

Yields:

Yield Parameters:

  • transaction (Transaction)

    The transaction object for making changes.

Returns:

  • (Object)

    The return value of the provided yield block

See Also:



787
788
789
790
# File 'lib/google/cloud/firestore/client.rb', line 787

def read_only_transaction read_time: nil
  transaction = Transaction.from_client self, read_time: read_time, read_only: true
  yield transaction
end

#transaction(max_retries: nil, commit_response: nil) {|transaction| ... } ⇒ Object, CommitResponse

Create a transaction to perform multiple reads and writes that are executed atomically at a single logical point in time in a database.

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

Examples:

require "google/cloud/firestore"

firestore = Google::Cloud::Firestore.new

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

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

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

Parameters:

  • max_retries (Integer) (defaults to: nil)

    The maximum number of retries for transactions failed due to errors. Default is 5. Optional.

  • commit_response (Boolean) (defaults to: nil)

    When true, the return value from this method will be a Google::Cloud::Firestore::CommitResponse object with a commit_time attribute. Otherwise, the return value from this method will be the return value of the provided yield block. Default is false. Optional.

Yields:

  • (transaction)

    The block for reading data and making changes.

Yield Parameters:

  • transaction (Transaction)

    The transaction object for making changes.

Returns:

  • (Object, CommitResponse)

    The return value of the provided yield block, or if commit_response is provided and true, the CommitResponse object from the commit operation.

See Also:



700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
# File 'lib/google/cloud/firestore/client.rb', line 700

def transaction max_retries: nil, commit_response: nil
  max_retries = 5 unless max_retries.is_a? Integer
  backoff = { current: 0, delay: 1.0, max: max_retries, mod: 1.3 }

  transaction = Transaction.from_client self
  begin
    transaction_return = yield transaction
    commit_return = transaction.commit
    # Conditional return value, depending on truthy commit_response
    commit_response ? commit_return : transaction_return
  rescue Google::Cloud::AbortedError,
         Google::Cloud::CanceledError,
         Google::Cloud::UnknownError,
         Google::Cloud::DeadlineExceededError,
         Google::Cloud::InternalError,
         Google::Cloud::UnauthenticatedError,
         Google::Cloud::ResourceExhaustedError,
         Google::Cloud::UnavailableError,
         Google::Cloud::InvalidArgumentError => e

    if e.instance_of? Google::Cloud::InvalidArgumentError
      # Return if a previous call was retried but ultimately succeeded
      return nil if backoff[:current].positive?
      # The Firestore backend uses "INVALID_ARGUMENT" for transaction IDs that have expired.
      # While INVALID_ARGUMENT is generally not retryable, we retry this specific case.
      raise e unless e.message =~ /transaction has expired/
    end

    # Re-raise if retried more than the max
    raise e if backoff[:current] > backoff[:max]

    # Sleep with incremental backoff before restarting
    sleep backoff[:delay]

    # Update increment backoff delay and retry counter
    backoff[:delay] *= backoff[:mod]
    backoff[:current] += 1

    # Create new transaction and retry
    transaction = Transaction.from_client \
      self, previous_transaction: transaction.transaction_id
    retry
  rescue StandardError => e
    # Rollback transaction when handling unexpected error
    transaction.rollback rescue nil

    # Re-raise error.
    raise e
  end
end