class Couchbase::View

This class implements Couchbase View execution

@see www.couchbase.com/docs/couchbase-manual-2.0/couchbase-views.html

Attributes

design_doc[R]
name[R]
params[R]

Public Class Methods

new(bucket, endpoint, params = {}) click to toggle source

Set up view endpoint and optional params

@param [Couchbase::Bucket] bucket Connection object which

stores all info about how to make requests to Couchbase views.

@param [String] endpoint Full Couchbase View URI.

@param [Hash] params Optional parameter which will be passed to

{View#fetch}
# File lib/couchbase/view.rb, line 87
def initialize(bucket, endpoint, params = {})
  @bucket   = bucket
  @endpoint = endpoint
  @design_doc, @name = parse_endpoint(endpoint)
  @wrapper_class = params.delete(:wrapper_class) || ViewRow
  @params   = { :connection_timeout => 75_000 }.merge(params)
  unless @wrapper_class.respond_to?(:wrap)
    raise ArgumentError, "wrapper class should reposond to :wrap, check the options"
  end
end

Public Instance Methods

each(params = {}) { |doc| ... } click to toggle source

Yields each document that was fetched by view. It doesn't instantiate all the results because of streaming JSON parser. Returns Enumerator unless block given.

@param [Hash] params Params for Couchdb query. Some useful are:

:start_key, :start_key_doc_id, :descending. See {View#fetch}.

@example Use each method with block

view.each do |doc|
  # do something with doc
end

@example Use Enumerator version

enum = view.each  # request hasn't issued yet
enum.map{|doc| doc.title.upcase}

@example Pass options during view initialization

endpoint = "http://localhost:5984/default/_design/blog/_view/recent"
view = View.new(conn, endpoint, :descending => true)
view.each do |document|
  # do something with document
end
# File lib/couchbase/view.rb, line 124
def each(params = {})
  return enum_for(:each, params) unless block_given?
  fetch(params) { |doc| yield(doc) }
end
fetch(params = {}) click to toggle source

Performs query to Couchbase view. This method will stream results if block given or return complete result set otherwise. In latter case it defines method total_rows returning corresponding entry from Couchbase result object.

@note Avoid using +$+ symbol as prefix for properties in your

documents, because server marks with it meta fields like flags and
expiration, therefore dollar prefix is some kind of reserved. It
won't hurt your application. Currently the {ViewRow}
class extracts +$flags+, +$cas+ and +$expiration+ properties from
the document and store them in {ViewRow#meta} hash.

@param [Hash] params parameters for Couchbase query. @option params [true, false] :include_docs (false) Include the

full content of the documents in the return. Note that the document
is fetched from the in memory cache where it may have been changed
or even deleted. See also +:quiet+ parameter below to control error
reporting during fetch.

@option params [true, false] :quiet (true) Do not raise error if

associated document not found in the memory. If the parameter +true+
will use +nil+ value instead.

@option params [true, false] :descending (false) Return the documents

in descending by key order

@option params [String, Fixnum, Hash, Array] :key Return only

documents that match the specified key. Will be JSON encoded.

@option params [Array] :keys The same as :key, but will work for

set of keys. Will be JSON encoded.

@option params [String, Fixnum, Hash, Array] :startkey Return

records starting with the specified key. +:start_key+ option should
also work here. Will be JSON encoded.

@option params [String] :startkey_docid Document id to start with

(to allow pagination for duplicate startkeys). +:start_key_doc_id+
also should work.

@option params [String, Fixnum, Hash, Array] :endkey Stop returning

records when the specified key is reached. +:end_key+ option should
also work here. Will be JSON encoded.

@option params [String] :endkey_docid Last document id to include

in the output (to allow pagination for duplicate startkeys).
+:end_key_doc_id+ also should work.

@option params [true, false] :inclusive_end (true) Specifies whether

the specified end key should be included in the result

@option params [Fixnum] :limit Limit the number of documents in the

output.

@option params [Fixnum] :skip Skip this number of records before

starting to return the results.

@option params [String, Symbol] :on_error (:continue) Sets the

response in the event of an error. Supported values:
:continue:: Continue to generate view information in the event of an
            error, including the error information in the view
            response stream.
:stop::     Stop immediately when an error condition occurs. No
            further view information will be returned.

@option params [Fixnum] :connection_timeout (75000) Timeout before the

view request is dropped (milliseconds)

@option params [true, false] :reduce (true) Use the reduction function @option params [true, false] :group (false) Group the results using

the reduce function to a group or single row.

@option params [Fixnum] :group_level Specify the group level to be

used.

@option params [String, Symbol, false] :stale (:update_after) Allow

the results from a stale view to be used. Supported values:
false::         Force a view update before returning data
:ok::           Allow stale views
:update_after:: Allow stale view, update view after it has been
                accessed

@option params [Hash] :body Accepts the same parameters, except

+:body+ of course, but sends them in POST body instead of query
string. It could be useful for really large and complex parameters.

@yieldparam [Couchbase::ViewRow] document

@return [Array] with documents. There will be total_entries

method defined on this array if it's possible.

@raise [Couchbase::Error::View] when on_error callback is nil and

error object found in the result stream.

@example Query recent_posts view with key filter

doc.recent_posts(:body => {:keys => ["key1", "key2"]})

@example Fetch second page of result set (splitted in 10 items per page)

page = 2
per_page = 10
doc.recent_posts(:skip => (page - 1) * per_page, :limit => per_page)

@example Simple join using Map/Reduce

# Given the bucket with Posts(:id, :type, :title, :body) and
# Comments(:id, :type, :post_id, :author, :body). The map function
# below (in javascript) will build the View index called
# "recent_posts_with_comments" which will behave like left inner join.
#
#   function(doc) {
#     switch (doc.type) {
#       case "Post":
#         emit([doc.id, 0], null);
#         break;
#       case "Comment":
#         emit([doc.post_id, 1], null);
#         break;
#     }
#   }
#
post_id = 42
doc.recent_posts_with_comments(:start_key => [post_id, 0],
                               :end_key => [post_id, 1],
                               :include_docs => true)
# File lib/couchbase/view.rb, line 286
def fetch(params = {})
  params = @params.merge(params)
  include_docs = params[:include_docs]
  quiet = params.fetch(:quiet, true)

  view = @bucket.client.getView(@design_doc, @name)

  query = Query.new(params)

  request = @bucket.client.query(view, query.generate)

  if block_given?
    block = Proc.new
    request.each do |data|
      doc = @wrapper_class.wrap(@bucket, data.getDocument)
      block.call(doc)
    end
    nil
  else
    docs = request.to_a.map { |data|
      @wrapper_class.wrap(@bucket, data.getDocument)
    }
    docs = ArrayWithTotalRows.new(docs)
    docs.total_rows = request.size
    docs
  end
end
fetch_all(params = {}, &block) click to toggle source

Method for fetching asynchronously all rows and passing array to callback

Parameters are same as for {View#fetch} method, but callback is called for whole set for rows instead of one by each.

@example

con.run do
  doc.recent_posts.fetch_all do |posts|
    do_something_with_all_posts(posts)
  end
end
# File lib/couchbase/view.rb, line 325
def fetch_all(params = {}, &block)
  return fetch(params) unless @bucket.async?
  raise ArgumentError, "Block needed for fetch_all in async mode" unless block

  all = []
  fetch(params) do |row|
    all << row
    if row.last?
      @bucket.create_timer(0) { block.call(all) }
    end
  end
end
first(params = {}) click to toggle source
# File lib/couchbase/view.rb, line 129
def first(params = {})
  params = params.merge(:limit => 1)
  fetch(params).first
end
inspect() click to toggle source

Returns a string containing a human-readable representation of the {View}

@return [String]

# File lib/couchbase/view.rb, line 342
def inspect
  %(#<#{self.class.name}:#{self.object_id} @endpoint=#{@endpoint.inspect} @params=#{@params.inspect}>)
end
on_error(&callback) click to toggle source

Registers callback function for handling error objects in view results stream.

@yieldparam [String] from Location of the node where error occured @yieldparam [String] reason The reason message describing what

happened.

@example Using #on_error to log all errors in view result

# JSON-encoded view result
#
# {
#   "total_rows": 0,
#   "rows": [ ],
#   "errors": [
#     {
#       "from": "127.0.0.1:5984",
#       "reason": "Design document `_design/testfoobar` missing in database `test_db_b`."
#     },
#     {
#       "from": "http:// localhost:5984/_view_merge/",
#       "reason": "Design document `_design/testfoobar` missing in database `test_db_c`."
#     }
#   ]
# }

view.on_error do |from, reason|
  logger.warn("#{view.inspect} received the error '#{reason}' from #{from}")
end
docs = view.fetch

@example More concise example to just count errors

errcount = 0
view.on_error{|f,r| errcount += 1}.fetch
# File lib/couchbase/view.rb, line 175
def on_error(&callback)
  @on_error = callback
  self  # enable call chains
end
take(n, params = {}) click to toggle source
# File lib/couchbase/view.rb, line 134
def take(n, params = {})
  params = params.merge(:limit => n)
  fetch(params)
end

Private Instance Methods

parse_endpoint(endpoint) click to toggle source
# File lib/couchbase/view.rb, line 358
def parse_endpoint(endpoint)
  parts = endpoint.split('/')
  if endpoint =~ /^_design/
    [parts[1], parts[3]]
  else
    [parts[0], parts[2]]
  end
end
send_error(*args) click to toggle source
# File lib/couchbase/view.rb, line 348
def send_error(*args)
  if @on_error
    @on_error.call(*args.take(2))
  else
    raise Error::View.new(*args)
  end
end