Class: CouchbaseOrm::Relation::CouchbaseOrm_Relation

Inherits:
Object
  • Object
show all
Defined in:
lib/couchbase-orm/relation.rb

Instance Method Summary collapse

Constructor Details

#initialize(model:, where: where = nil, order: order = nil, limit: limit = nil, _not: _not = false) ⇒ CouchbaseOrm_Relation

Returns a new instance of CouchbaseOrm_Relation.



8
9
10
11
12
13
14
15
16
17
# File 'lib/couchbase-orm/relation.rb', line 8

def initialize(model:, where: where = nil, order: order = nil, limit: limit = nil, _not: _not = false)
  CouchbaseOrm.logger.debug "CouchbaseOrm_Relation init: #{model} where:#{where.inspect} not:#{_not.inspect} order:#{order.inspect} limit: #{limit}"
  @model = model
  @limit = limit
  @where = []
  @order = {}
  @order = merge_order(**order) if order
  @where = merge_where(where, _not) if where
  CouchbaseOrm.logger.debug "- #{self}"
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object (private)



539
540
541
542
543
544
545
546
547
# File 'lib/couchbase-orm/relation.rb', line 539

def method_missing(method, *args, &block)
  if @model.respond_to?(method)
    scoping {
      @model.public_send(method, *args, &block)
    }
  else
    super
  end
end

Instance Method Details

#[](*args) ⇒ Object



261
262
263
# File 'lib/couchbase-orm/relation.rb', line 261

def [](*args)
  to_ary[*args]
end

#allCouchbaseOrm_Relation

Initializes a new query relation to fetch all records from the database.

This method creates a new `CouchbaseOrm_Relation` instance, setting the stage for a query that can fetch all records. It serves as a base that can be extended with further conditions, limits, orders, etc.

Examples:

Fetch all users and apply additional query conditions

class User < Couchbase::Base

  def self.fetch_all_active_users
    all.where(active: true).order(created_at: :desc)
  end
end

active_users = User.fetch_all_active_users
# This initializes a query to fetch all users, then narrows it down to active users,
# and orders them by their creation date in descending order.

Returns:



420
421
422
# File 'lib/couchbase-orm/relation.rb', line 420

def all
  CouchbaseOrm_Relation.new(**initializer_arguments)
end

#countInteger Also known as: size, length

Retrieves the count of documents that match the current query conditions.

This method constructs and executes a N1QL query based on the current state of the instance and returns the count of documents that match the query conditions.

Returns:

  • (Integer)

    The count of documents that match the query conditions.



184
185
186
# File 'lib/couchbase-orm/relation.rb', line 184

def count
  query.count
end

#delete_allvoid

This method returns an undefined value.

Deletes all documents that match the current query conditions.

This method constructs and executes a N1QL query to get the IDs of the matching documents and then deletes them using the model's `remove_multi` method.

Examples:

Delete all inactive users

class User < Couchbase::Base

  def self.delete_inactive_users
    where(active: false).delete_all
  end
end

User.delete_inactive_users
# This will construct and execute the N1QL query to retrieve the IDs of all inactive users
# and delete the corresponding documents.


283
284
285
286
287
# File 'lib/couchbase-orm/relation.rb', line 283

def delete_all
  CouchbaseOrm.logger.debug{ "Delete all: #{self}" }
  ids = query.to_a
  @model.collection.remove_multi(ids) unless ids.empty?
end

#empty?Boolean

Checks if there are any documents that match the current query conditions.

This method constructs and executes a N1QL query with a limit of 1 document and returns true if no documents match the query conditions.

Returns:

  • (Boolean)

    True if no documents match the query conditions, false otherwise.



194
195
196
# File 'lib/couchbase-orm/relation.rb', line 194

def empty?
  limit(1).count.zero?
end

#execute(n1ql_query) ⇒ N1qlProxy

Executes a N1QL query on the Couchbase cluster and returns the results.

This method runs the provided N1QL query using the Couchbase cluster associated with the model. It ensures the query is executed with a consistent view of the data. The results are logged and returned wrapped in a `N1qlProxy` object.

Examples:

Execute a N1QL query to find active users

class User < CouchbaseOrm::Base

  def self.active_users
    n1ql_query = where(active: true)
                    .order(created_at: :desc)
                    .limit(10)
                    .to_n1ql
    execute(n1ql_query)
  end
end

results = User.active_users
# This will execute the N1QL query and return the results wrapped in a `N1qlProxy` object.
# You can iterate over the results, access specific fields, etc.

Parameters:

  • n1ql_query (String)

    The N1QL query to be executed.

Returns:

  • (N1qlProxy)

    The results of the query wrapped in a `N1qlProxy` object.



71
72
73
74
75
# File 'lib/couchbase-orm/relation.rb', line 71

def execute(n1ql_query)
  result = @model.cluster.query(n1ql_query, Couchbase::Options::Query.new(scan_consistency: :request_plus))
  CouchbaseOrm.logger.debug { "Relation query: #{n1ql_query} return #{result.rows.to_a.length} rows" }
  N1qlProxy.new(result)
end

#find_by(**conds) ⇒ Object?

Finds the first record that matches the given conditions.

This method constructs a query with the specified conditions and returns the first matching record.

Examples:

Find a user by email

class User < Couchbase::Base

  def self.find_by_email(email)
    find_by(email: email)
  end
end
user = User.find_by_email('example@example.com')
# This will create a query with the condition for email and return the first matching user.

Parameters:

  • conds (Hash)

    Conditions as key-value pairs.

Returns:

  • (Object, nil)

    The first record that matches the conditions, or nil if no record matches.



329
330
331
# File 'lib/couchbase-orm/relation.rb', line 329

def find_by(**conds)
  CouchbaseOrm_Relation.new(**initializer_arguments.merge(where: merge_where(conds))).first
end

#firstObject?

Retrieves the first document that matches the current query conditions.

This method modifies the current query to limit the result to 1 document, executes the query, and returns the first document that matches the query conditions.

Returns:

  • (Object, nil)

    The first document that matches the query conditions, or nil if no documents match.



159
160
161
162
163
164
# File 'lib/couchbase-orm/relation.rb', line 159

def first
  result = @model.cluster.query(self.limit(1).to_n1ql,
                                Couchbase::Options::Query.new(scan_consistency: :request_plus))
  first_id = result.rows.to_a.first
  @model.find(first_id) if first_id
end

#idsArray<String>

Executes the current query and returns the result as an array of document IDs.

This method constructs and executes a N1QL query based on the current state of the instance, and converts the result to an array of document IDs.

Examples:

Retrieve IDs of active users created before a certain date

class User < CouchbaseOrm::Base

  def self.active_users
    where(active: true)
      .order(created: :desc)
      .limit(10)
      .ids
  end
end

user_ids = User.active_user_ids
# This will construct and execute the N1QL query to retrieve the IDs of active users
# created before a certain date, and return the result as an array of document IDs.
# You can iterate over the IDs, fetch specific documents by ID, etc.

Returns:

  • (Array<String>)

    An array of document IDs.



149
150
151
# File 'lib/couchbase-orm/relation.rb', line 149

def ids
  query.to_a
end

#lastObject?

Retrieves the last document that matches the current query conditions.

This method executes the query, and returns the last document that matches the query conditions.

Returns:

  • (Object, nil)

    The last document that matches the query conditions, or nil if no documents match.



172
173
174
175
176
# File 'lib/couchbase-orm/relation.rb', line 172

def last
  result = @model.cluster.query(to_n1ql, Couchbase::Options::Query.new(scan_consistency: :request_plus))
  last_id = result.rows.to_a.last
  @model.find(last_id) if last_id
end

#limit(limit) ⇒ CouchbaseOrm_Relation

Sets a limit on the number of results to be returned by the query.

This method updates the query configuration to include a specified limit, controlling the amount of data retrieved from the database. It returns a new `CouchbaseOrm_Relation` instance with the updated configuration.

Examples:

Retrieve only 5 users

class User < Couchbase::Base

  def self.find_top_five
    limit(5)
  end
end

top_five_users = User.find_top_five
# This will return only the first five user records from the query.

Parameters:

  • limit (Integer)

    The maximum number of records to return.

Returns:



398
399
400
# File 'lib/couchbase-orm/relation.rb', line 398

def limit(limit)
  CouchbaseOrm_Relation.new(**initializer_arguments.merge(limit: limit))
end

#not(**conds) ⇒ CouchbaseOrm_Relation

Adds negation conditions to the query.

This method allows you to specify conditions that should not be matched by the query. It returns a new `CouchbaseOrm_Relation` instance with the updated conditions.

Examples:

Exclude users with a specific role

class User < Couchbase::Base

  def self.exclude_role(role)
    not(role: role)
  end
end

non_admins = User.exclude_role('admin')
# This will create a query excluding users with the 'admin' role.

Parameters:

  • conds (Hash)

    Conditions as key-value pairs that should be negated.

Returns:



351
352
353
# File 'lib/couchbase-orm/relation.rb', line 351

def not(**conds)
  CouchbaseOrm_Relation.new(**initializer_arguments.merge(where: merge_where(conds, _not: true)))
end

#order(*lorder, **horder) ⇒ CouchbaseOrm_Relation

Specifies the order of the results for the query.

This method allows for the specification of how query results should be ordered, using both positional and named arguments. It returns a new `CouchbaseOrm_Relation` instance with the updated order conditions.

Examples:

Order users by creation date in descending order

class User < Couchbase::Base

  def self.order_by_creation_desc
    order(created_at: :desc)
  end
end

ordered_users = User.order_by_creation_desc
# This will create a query with an order condition for users ordered by 'created_at' descending.

Parameters:

  • lorder (Array<String, Symbol>)

    Positional ordering parameters.

  • horder (Hash)

    Named ordering parameters with directions.

Returns:



375
376
377
# File 'lib/couchbase-orm/relation.rb', line 375

def order(*lorder, **horder)
  CouchbaseOrm_Relation.new(**initializer_arguments.merge(order: merge_order(*lorder, **horder)))
end

#pluck(*fields) ⇒ Array<Object>

Retrieves specific fields from the documents that match the current query conditions.

This method constructs and executes a N1QL query to retrieve the specified fields from the documents that match the current query conditions.

Examples:

Retrieve the names of all active users

class User < Couchbase::Base

  def self.active_user_names
    where(active: true).pluck(:name)
  end
end

active_user_names = User.active_user_names
# This will construct and execute the N1QL query to retrieve the names of all active users
# and return an array of names.

Parameters:

  • fields (Array<Symbol>)

    The fields to retrieve from the documents.

Returns:

  • (Array<Object>)

    An array of field values for each document.



217
218
219
220
221
222
223
224
225
226
227
# File 'lib/couchbase-orm/relation.rb', line 217

def pluck(*fields)
  map do |model|
    if fields.length == 1
      model.send(fields.first)
    else
      fields.map do |field|
        model.send(field)
      end
    end
  end
end

#queryN1qlProxy

Constructs and executes a N1QL query for Couchbase based on the current state of the instance.

Examples:

Execute a query to find active users

class User < CouchbaseOrm::Base

  def self.active_users
    where(active: true)
      .order(created_at: :desc)
      .limit(10)
      .query
  end
end

results = User.active_users
# This will execute the N1QL query and return the results wrapped in a `N1qlProxy` object.
# You can iterate over the results, access specific fields, etc.

Returns:

  • (N1qlProxy)

    The results of the query wrapped in a `N1qlProxy` object.



95
96
97
98
99
# File 'lib/couchbase-orm/relation.rb', line 95

def query
  CouchbaseOrm.logger.debug("Query: #{self}")
  n1ql_query = to_n1ql
  execute(n1ql_query)
end

#scoping { ... } ⇒ Object

Temporarily modifies the query scope within a block of code in a thread-safe manner.

This method is used to apply temporary query conditions which are only meant to last during the execution of the given block. It ensures that the scope is added before the block is executed and properly removed afterward, even if an exception occurs.

Examples:

Apply a temporary scope to increase salary for specific calculations

class Employee  < Couchbase::Base

  def self.temporary_increase(factor)
    scoping do
      where(salary: salary.map { |s| s * factor })
      # Other operations that depend on this temporary scope
    end
  end
end

Employee.temporary_increase(1.10)
# This will temporarily increase the salary by 10% within the block, for whatever operations are needed.

Yields:

  • The block during which the temporary scope should be applied.

Returns:

  • (Object)

    The result of the block execution.



446
447
448
449
450
451
452
453
# File 'lib/couchbase-orm/relation.rb', line 446

def scoping
  scopes = (Thread.current[@model.name] ||= [])
  scopes.push(self)
  result = yield
ensure
  scopes.pop
  result
end

#to_aryArray<Object> Also known as: to_a

Converts the results of the current query into an array of model instances.

This method executes the current query to get the IDs of the matching documents, fetches the documents using the model's `find` method, and returns them as an array.

Examples:

Retrieve all active users as an array

class User < Couchbase::Base

  def self.active_users
    where(active: true).to_ary
  end
end

active_users = User.active_users
# This will construct and execute the N1QL query to retrieve the IDs of all active users,
# fetch the corresponding documents, and return them as an array of user instances.

Returns:

  • (Array<Object>)

    An array of model instances that match the query conditions.



250
251
252
253
254
255
# File 'lib/couchbase-orm/relation.rb', line 250

def to_ary
  ids = query.results
  return [] if ids.empty?

  Array(ids && @model.find(ids))
end

#to_n1qlString

Constructs a N1QL query string for Couchbase to select document IDs based on defined criteria.

N1QL (Non-first Normal Form Query Language) is a powerful query language for Couchbase that allows you to perform complex queries on your data. For more details, see the [Couchbase N1QL Documentation](docs.couchbase.com/server/current/n1ql/n1ql-intro/index.html).

Examples:

Construct a N1QL query to find document IDs with specific criteria

class User < Couchbase::Base
  attribute :active, type: :bool
end

user_query = User.where(active: true)
                 .to_n1ql
# user_query => "select raw meta().id from `bucket_name` where type = 'user' and active = true"

Returns:

  • (String)

    The constructed N1QL query string.



39
40
41
42
43
44
45
# File 'lib/couchbase-orm/relation.rb', line 39

def to_n1ql
  bucket_name = @model.bucket.name
  where = build_where
  order = build_order
  limit = build_limit
  "select raw meta().id from `#{bucket_name}` where #{where} order by #{order} #{limit}"
end

#to_sObject



19
20
21
# File 'lib/couchbase-orm/relation.rb', line 19

def to_s
  "CouchbaseOrm_Relation: #{@model} where:#{@where.inspect} order:#{@order.inspect} limit: #{@limit}"
end

#update_all(**cond) ⇒ N1qlProxy

Updates all documents in the Couchbase bucket that match the specified conditions.

This method constructs and executes a N1QL query to update documents in the Couchbase bucket based on the specified conditions. It logs the query execution and returns the results.

Examples:

Update the 'active' status of users created before a certain date

class User < CouchbaseOrm::Base
 # attributes
end

results = User.where("created_at < '2023-01-01'").update_all(active: false)
# This will construct and execute the N1QL query to update all users created before 2023-01-01
# to have 'active' set to false.
# You can iterate over the results, check the status, etc.

Parameters:

  • cond (Hash)

    The conditions to update the documents with.

Returns:

  • (N1qlProxy)

    The results of the update operation wrapped in a `N1qlProxy` object.



118
119
120
121
122
123
124
125
# File 'lib/couchbase-orm/relation.rb', line 118

def update_all(**cond)
  bucket_name = @model.bucket.name
  where = build_where
  limit = build_limit
  update = build_update(**cond)
  n1ql_query = "update `#{bucket_name}` set #{update} where #{where} #{limit}"
  execute(n1ql_query)
end

#where(string_cond = nil, **conds) ⇒ CouchbaseOrm_Relation

Adds conditions to the query.

This method allows you to specify query conditions using a string and/or a hash. It returns a new `CouchbaseOrm_Relation` instance with the updated conditions.

Examples:

Find all active users with a specific role

class User < Couchbase::Base

  def self.active_with_role(role)
    where(active: true).where(role: role)
  end
end

active_admins = User.active_with_role('admin')
# This will create a query with conditions for active users with the role 'admin'
# and return a new `CouchbaseOrm_Relation` instance with these conditions.

Parameters:

  • string_cond (String, nil) (defaults to: nil)

    Additional conditions in a string format (optional).

  • conds (Hash)

    Conditions as key-value pairs (optional).

Returns:



309
310
311
# File 'lib/couchbase-orm/relation.rb', line 309

def where(string_cond = nil, **conds)
  CouchbaseOrm_Relation.new(**initializer_arguments.merge(where: merge_where(conds) + string_where(string_cond)))
end