Class: ChillDB::Design

Inherits:
Object
  • Object
show all
Defined in:
lib/chill.rb

Overview

Representing a named design in the Couch database, Design is used to setup views. Views index all of the documents in your database, creating ChillDB::List’s for each emitted document. Your views can choose to emit as many entries as you like for each document, or none at all. Views can be as simple as listing all of a certain kind of document, or more complex schemes like extracting every word in a document and generating an index of words in documents for a simple but powerful search engine.

For more information on designs and views, CouchDB: The Definitive Guide is a great resource. guide.couchdb.org/draft/design.html

Example:

KittensApp.design(:lists).views(
  # lists all cats with a softness rating of two or more
  soft_cats: 'function(doc) {
    if (doc.kind == "cat" && doc.softness > 1) emit(doc._id, null);
  }'
).commit!

Note that views default to being javascript functions, as this is what couch ships with support for. It is possible to

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(database, name) ⇒ Design

Returns a new instance of Design.



764
765
766
767
# File 'lib/chill.rb', line 764

def initialize database, name
  @database = database
  @name = name.to_s
end

Instance Attribute Details

#nameObject

Returns the value of attribute name.



762
763
764
# File 'lib/chill.rb', line 762

def name
  @name
end

Instance Method Details

#add_views(collection) ⇒ Object

Add more views to an existing design. See also #views



778
779
780
781
# File 'lib/chill.rb', line 778

def add_views collection
  document['views'].merge! views_preprocess(collection)
  return self
end

#commit!Object

Commit this design document to the server and start the server’s process of updating the view’s contents. Note that querying the view immediately after a commit may be slow, while the server finishes initially processing it’s contents. The more documents you have, the more time this can take.



850
851
852
853
# File 'lib/chill.rb', line 850

def commit!
  document['_id'] = "_design/#{@name}"
  document.commit!
end

#documentObject

lazy load document - referencing this causes load from database



770
771
772
773
774
775
# File 'lib/chill.rb', line 770

def document
  @document ||= ChillDB::Document::load @database, "_design/#{@name}"
  @document['language'] ||= 'javascript'
  @document['views'] ||= {}
  return @document
end

#language(set = nil) ⇒ Object

get’s the current language of this design document. Usually this would be “javascript”. If called with an argument, set’s the language property and returns self.

Example:

KittensApp.design(:lists).language #=> "javascript"
KittensApp.design(:lists).language(:ruby) #=> KittensApp.design(:lists)
KittensApp.design(:lists).language #=> "ruby"

# chain it together with views for extra nyan:
KittensApp.design(:lists).language(:ruby).views(
  soft_cats: %q{ proc do |doc|
    emit doc['_id'], doc['softness'] if doc['softness'] > 1 
  end }
)

ChillDB doesn’t currently include a ruby view server, and it needs to be specifically configured and installed before you can use one. More info in an implementation is at theexciter.com/articles/couchdb-views-in-ruby-instead-of-javascript.html



837
838
839
840
841
842
843
844
# File 'lib/chill.rb', line 837

def language set = nil
  if set
    @document['language'] = set.to_s
    self
  else
    @document['language']
  end
end

#query(view, options = {}) ⇒ Object

Query a named view. Returns a ChillDB::List, which works like a Hash or an Array containing each result. Optionally pass in arguments. Check out wiki.apache.org/couchdb/HTTP_view_API#Querying_Options for the definitive list. Some really useful options:

Options:

include_docs: (true or false) load documents which emitted each entry?
key: only return items emitted with this exact key
keys: (Array) only return items emitted with a key in this Array
range: (Range) shortcut for startkey, endkey, and inclusive_end
startkey: return items starting with this key
endkey: return items ending with this key
startkey_docid: (String) return items starting with this document id
endkey_docid: (String) return items ending with this document id
inclusive_end: (true or false) defaults true, endkey included in result?
limit: (Number) of documents to load before stopping
stale: (String) 'ok' or 'update_after' - view need not be up to date.
descending: (true or false) direction of search?
skip: (Number) skip the first few documents - slow - not recomended!
group: (true or false) should reduce grouping by exact identical key?
group_level: (Number) first x items in key Array are used to group rows
reduce: (true or false) should the reduce function be used?
update_seq: (true or false) response includes sequence id of database?


878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
# File 'lib/chill.rb', line 878

def query view, options = {}
  if options[:range]
    range = options.delete[:range]
    options[:startkey], options[:endkey] = range.first, range.last
    options[:startkey], options[:endkey] = options[:endkey], options[:startkey] if options[:descending]
    options[:inclusive_end] = !range.exclude_end?
  end
  
  # these options need to be json encoded
  [:key, :startkey, :endkey, :keys, :descending, :limit, :skip, :group, :group_level,
   :reduce, :include_docs, :inclusive_end, :update_seq
  ].each do |name|
    options[name] = options[name].to_json if options.has_key? name
  end
  
  opts = options.map { |key, value| "#{URI.escape(key.to_s)}=#{URI.escape(value.to_s)}" }.join('&')
  url = "_design/#{URI.escape @name}/_view/#{URI.escape view.to_s}?#{opts}"
  response = @database.http(url).get()
  
  # put the results in to a QueryResults object - a glorified array
  return ChillDB::List.load(JSON.parse(response.body), database: @database)
end

#views(collection) ⇒ Object

Set the views in this design. Argument is a Hash containing String’s for each javascript (by default) view function. Reduce functions can also be included optionally.

Example:

KittensApp.design(:lists).views(
  # just a map function
  adults: 'function(doc) {
    if (doc.kind == "cat" && doc.age > 4) emit(doc._id, null);
  }',

  # a map and a reduce - lookup the overall softness of our kitten database
  # when queried returns just one value: the number output of the reduce
  # function.
  softness: {
    map: 'function(doc) {
      if (doc.kind == "cat") emit(doc._id, doc.softness);
    }',
    reduce: 'function(key, values, rereduce) {
      return sum(values); // add them all together
    }'
  }
).commit!

KittensApp.design(:lists).query(:adults) #=> <ChillDB::List> [a, b, c...]
KittensApp.design(:lists).query(:softness) #=> 19

Check out wiki.apache.org/couchdb/Introduction_to_CouchDB_views for a great introduction to CouchDB view design.



812
813
814
815
816
# File 'lib/chill.rb', line 812

def views collection
  document['views'] = {}
  add_views collection
  return self
end