Object
Create a CouchRest::Database adapter for the supplied CouchRest::Server and database name.
server<CouchRest::Server> |
database host |
name<String> |
database name |
# File lib/couchrest/database.rb, line 16 def initialize(server, name) @name = name @server = server @host = server.uri @uri = "/#{name.gsub('/','%2F')}" @root = host + uri @streamer = Streamer.new @bulk_save_cache = [] @bulk_save_cache_limit = 500 # must be smaller than the uuid count end
Query the _all_docs view. Accepts all the same arguments as view.
# File lib/couchrest/database.rb, line 280 def all_docs(params = {}, payload = {}, &block) view("_all_docs", params, payload, &block) end
Save a document to CouchDB in batch mode. See save_doc's batch argument.
# File lib/couchrest/database.rb, line 158 def batch_save_doc(doc) save_doc(doc, false, true) end
POST an array of documents to CouchDB. If any of the documents are missing ids, supply one from the uuid cache.
If called with no arguments, bulk saves the cache of documents to be bulk saved.
# File lib/couchrest/database.rb, line 166 def bulk_save(docs = nil, use_uuids = true, all_or_nothing = false) if docs.nil? docs = @bulk_save_cache @bulk_save_cache = [] end if (use_uuids) ids, noids = docs.partition{|d|d['_id']} uuid_count = [noids.length, @server.uuid_batch_count].max noids.each do |doc| nextid = @server.next_uuid(uuid_count) rescue nil doc['_id'] = nextid if nextid end end request_body = {:docs => docs} if all_or_nothing request_body[:all_or_nothing] = true end CouchRest.post "#{@root}/_bulk_docs", request_body end
Save a document to CouchDB in bulk mode. See save_doc's bulk argument.
# File lib/couchrest/database.rb, line 153 def bulk_save_doc(doc) save_doc(doc, true) end
Query CouchDB's special _changes feed for the latest. All standard CouchDB options can be provided.
Warning: sending :feed => 'continuous' will cause your code to block indefinetly while waiting for changes. You might want to look-up an alternative to this.
# File lib/couchrest/database.rb, line 291 def changes(params = {}, payload = {}, &block) view("_changes", params, payload, &block) end
Compact the database, removing old document revisions and optimizing space use.
# File lib/couchrest/database.rb, line 40 def compact! CouchRest.post "#{@root}/_compact" end
COPY an existing document to a new id. If the destination id currently exists, a rev must be provided. dest can take one of two forms if overwriting: "id_to_overwrite?rev=revision" or the actual doc hash with a '_rev' key
# File lib/couchrest/database.rb, line 206 def copy_doc(doc, dest) raise ArgumentError, "_id is required for copying" unless doc['_id'] slug = escape_docid(doc['_id']) destination = if dest.respond_to?(:has_key?) && dest['_id'] && dest['_rev'] "#{dest['_id']}?rev=#{dest['_rev']}" else dest end CouchRest.copy "#{@root}/#{slug}", destination end
Create the database
# File lib/couchrest/database.rb, line 45 def create! bool = server.create_db(@name) rescue false bool && true end
DELETE the database itself. This is not undoable and could be rather catastrophic. Use with care!
# File lib/couchrest/database.rb, line 71 def delete! CouchRest.delete @root end
DELETE an attachment directly from CouchDB
# File lib/couchrest/database.rb, line 325 def delete_attachment(doc, name, force=false) uri = url_for_attachment(doc, name) # this needs a rev begin CouchRest.delete(uri) rescue Exception => error if force # get over a 409 doc = get(doc['_id']) uri = url_for_attachment(doc, name) CouchRest.delete(uri) else error end end end
DELETE the document from CouchDB that has the given _id and _rev.
If bulk is true (false by default) the deletion is recorded for bulk-saving (bulk-deletion :) later. Bulk saving happens automatically when bulk_save_cache limit is exceded, or on the next non bulk save.
# File lib/couchrest/database.rb, line 192 def delete_doc(doc, bulk = false) raise ArgumentError, "_id and _rev required for deleting" unless doc['_id'] && doc['_rev'] if bulk @bulk_save_cache << { '_id' => doc['_id'], '_rev' => doc['_rev'], :_deleted => true } return bulk_save if @bulk_save_cache.length >= @bulk_save_cache_limit return {'ok' => true} # Mimic the non-deferred version end slug = escape_docid(doc['_id']) CouchRest.delete "#{@root}/#{slug}?rev=#{doc['_rev']}" end
GET an attachment directly from CouchDB
# File lib/couchrest/database.rb, line 312 def fetch_attachment(doc, name) uri = url_for_attachment(doc, name) CouchRest.get uri, :raw => true end
Query a CouchDB-Lucene search view
# File lib/couchrest/database.rb, line 296 def fti(name, params={}) # -> http://localhost:5984/yourdb/_fti/YourDesign/by_name?include_docs=true&q=plop*' view("_fti/#{name}", params) end
GET a document from CouchDB, by id. Returns a Document or Design.
# File lib/couchrest/database.rb, line 79 def get(id, params = {}) slug = escape_docid(id) url = CouchRest.paramify_url("#{@root}/#{slug}", params) result = CouchRest.get(url) return result unless result.is_a?(Hash) doc = if /^_design/ =~ result["_id"] Design.new(result) else Document.new(result) end doc.database = self doc end
load a set of documents by passing an array of ids
# File lib/couchrest/database.rb, line 303 def get_bulk(ids) all_docs(:keys => ids, :include_docs => true) end
GET the database info from CouchDB
# File lib/couchrest/database.rb, line 35 def info CouchRest.get @root end
PUT an attachment directly to CouchDB
# File lib/couchrest/database.rb, line 318 def put_attachment(doc, name, file, options = {}) docid = escape_docid(doc['_id']) uri = url_for_attachment(doc, name) CouchRest.put(uri, file, options.merge(:raw => true)) end
Delete and re create the database
# File lib/couchrest/database.rb, line 51 def recreate! delete! create! rescue RestClient::ResourceNotFound ensure create! end
Replicates via "pulling" from another database to this database. Makes no attempt to deal with conflicts.
# File lib/couchrest/database.rb, line 60 def replicate_from(other_db, continuous = false, create_target = false, doc_ids = nil) replicate(other_db, continuous, :target => name, :create_target => create_target, :doc_ids => doc_ids) end
Replicates via "pushing" to another database. Makes no attempt to deal with conflicts.
# File lib/couchrest/database.rb, line 65 def replicate_to(other_db, continuous = false, create_target = false, doc_ids = nil) replicate(other_db, continuous, :source => name, :create_target => create_target, :doc_ids => doc_ids) end
Save a document to CouchDB. This will use the _id field from the document as the id for PUT, or request a new UUID from CouchDB, if no _id is present on the document. IDs are attached to documents on the client side because POST has the curious property of being automatically retried by proxies in the event of network segmentation and lost responses.
If bulk is true (false by default) the document is cached for bulk-saving later. Bulk saving happens automatically when bulk_save_cache limit is exceded, or on the next non bulk save.
If batch is true (false by default) the document is saved in batch mode, "used to achieve higher throughput at the cost of lower guarantees. When [...] sent using this option, it is not immediately written to disk. Instead it is stored in memory on a per-user basis for a second or so (or the number of docs in memory reaches a certain point). After the threshold has passed, the docs are committed to disk. Instead of waiting for the doc to be written to disk before responding, CouchDB sends an HTTP 202 Accepted response immediately. batch=ok is not suitable for crucial data, but it ideal for applications like logging which can accept the risk that a small proportion of updates could be lost due to a crash."
# File lib/couchrest/database.rb, line 114 def save_doc(doc, bulk = false, batch = false) if doc['_attachments'] doc['_attachments'] = encode_attachments(doc['_attachments']) end if bulk @bulk_save_cache << doc bulk_save if @bulk_save_cache.length >= @bulk_save_cache_limit return {'ok' => true} # Compatibility with Document#save elsif !bulk && @bulk_save_cache.length > 0 bulk_save end result = if doc['_id'] slug = escape_docid(doc['_id']) begin uri = "#{@root}/#{slug}" uri << "?batch=ok" if batch CouchRest.put uri, doc rescue RestClient::ResourceNotFound p "resource not found when saving even tho an id was passed" slug = doc['_id'] = @server.next_uuid CouchRest.put "#{@root}/#{slug}", doc end else begin slug = doc['_id'] = @server.next_uuid CouchRest.put "#{@root}/#{slug}", doc rescue #old version of couchdb CouchRest.post @root, doc end end if result['ok'] doc['_id'] = result['id'] doc['_rev'] = result['rev'] doc.database = self if doc.respond_to?(:database=) end result end
POST a temporary view function to CouchDB for querying. This is not recommended, as you don't get any performance benefit from CouchDB's materialized views. Can be quite slow on large databases.
# File lib/couchrest/database.rb, line 273 def temp_view(payload, params = {}, &block) view('_temp_view', params, payload, &block) end
returns the database's uri
# File lib/couchrest/database.rb, line 30 def to_s @root end
Updates the given doc by yielding the current state of the doc and trying to update update_limit times. Returns the doc if successfully updated without hitting the limit. If the limit is reached, the last execption will be raised.
# File lib/couchrest/database.rb, line 221 def update_doc(doc_id, params = {}, update_limit = 10) resp = {'ok' => false} last_fail = nil until resp['ok'] or update_limit <= 0 doc = self.get(doc_id, params) yield doc begin resp = self.save_doc doc rescue RestClient::RequestFailed => e if e.http_code == 409 # Update collision update_limit -= 1 last_fail = e else raise e end end end raise last_fail unless resp['ok'] doc end
Query a CouchDB view as defined by a _design document. Accepts paramaters as described in wiki.apache.org/couchdb/HttpViewApi
# File lib/couchrest/database.rb, line 249 def view(name, params = {}, payload = {}, &block) params = params.dup payload['keys'] = params.delete(:keys) if params[:keys] # Try recognising the name, otherwise assume already prepared view_path = name_to_view_path(name) url = CouchRest.paramify_url "#{@root}/#{view_path}", params if block_given? if !payload.empty? @streamer.post url, payload, &block else @streamer.get url, &block end else if !payload.empty? CouchRest.post url, payload else CouchRest.get url end end end
Generated with the Darkfish Rdoc Generator 2.