Class: CouchRest::Database
- Inherits:
-
Object
- Object
- CouchRest::Database
- Defined in:
- lib/couchrest/database.rb
Instance Attribute Summary collapse
-
#bulk_save_cache_limit ⇒ Object
Returns the value of attribute bulk_save_cache_limit.
-
#host ⇒ Object
readonly
Returns the value of attribute host.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#root ⇒ Object
readonly
Returns the value of attribute root.
-
#server ⇒ Object
readonly
Returns the value of attribute server.
-
#uri ⇒ Object
readonly
Returns the value of attribute uri.
Instance Method Summary collapse
-
#batch_save_doc(doc) ⇒ Object
Save a document to CouchDB in batch mode.
-
#bulk_save(docs = nil, use_uuids = true) ⇒ Object
(also: #bulk_delete)
POST an array of documents to CouchDB.
-
#bulk_save_doc(doc) ⇒ Object
Save a document to CouchDB in bulk mode.
-
#compact! ⇒ Object
Compact the database, removing old document revisions and optimizing space use.
-
#copy_doc(doc, dest) ⇒ Object
COPY an existing document to a new id.
-
#create! ⇒ Object
Create the database.
-
#delete! ⇒ Object
DELETE the database itself.
-
#delete_attachment(doc, name, force = false) ⇒ Object
DELETE an attachment directly from CouchDB.
-
#delete_doc(doc, bulk = false) ⇒ Object
DELETE the document from CouchDB that has the given
_id
and_rev
. -
#documents(params = {}) ⇒ Object
Query the
_all_docs
view. -
#fetch_attachment(doc, name) ⇒ Object
GET an attachment directly from CouchDB.
-
#get(id, params = {}) ⇒ Object
GET a document from CouchDB, by id.
-
#get_bulk(ids) ⇒ Object
(also: #bulk_load)
load a set of documents by passing an array of ids.
-
#info ⇒ Object
GET the database info from CouchDB.
-
#initialize(server, name) ⇒ Database
constructor
Create a CouchRest::Database adapter for the supplied CouchRest::Server and database name.
-
#put_attachment(doc, name, file, options = {}) ⇒ Object
PUT an attachment directly to CouchDB.
-
#recreate! ⇒ Object
Delete and re create the database.
-
#replicate_from(other_db, continuous = false, create_target = false) ⇒ Object
Replicates via “pulling” from another database to this database.
-
#replicate_to(other_db, continuous = false, create_target = false) ⇒ Object
Replicates via “pushing” to another database.
-
#save_doc(doc, bulk = false, batch = false) ⇒ Object
Save a document to CouchDB.
-
#search(name, params = {}) ⇒ Object
Query a CouchDB-Lucene search view.
-
#slow_view(funcs, params = {}) ⇒ Object
(also: #temp_view)
POST a temporary view function to CouchDB for querying.
-
#to_s ⇒ Object
returns the database’s uri.
-
#update_doc(doc_id, params = {}, update_limit = 10) ⇒ Object
Updates the given doc by yielding the current state of the doc and trying to update update_limit times.
-
#view(name, params = {}, &block) ⇒ Object
Query a CouchDB view as defined by a
_design
document.
Constructor Details
#initialize(server, name) ⇒ Database
Create a CouchRest::Database adapter for the supplied CouchRest::Server and database name.
Parameters
- server<CouchRest::Server>
-
database host
- name<String>
-
database name
18 19 20 21 22 23 24 25 26 27 |
# File 'lib/couchrest/database.rb', line 18 def initialize(server, name) @name = name @server = server @host = server.uri @uri = "/#{name.gsub('/','%2F')}" @root = host + uri @streamer = Streamer.new(self) @bulk_save_cache = [] @bulk_save_cache_limit = 500 # must be smaller than the uuid count end |
Instance Attribute Details
#bulk_save_cache_limit ⇒ Object
Returns the value of attribute bulk_save_cache_limit.
9 10 11 |
# File 'lib/couchrest/database.rb', line 9 def bulk_save_cache_limit @bulk_save_cache_limit end |
#host ⇒ Object (readonly)
Returns the value of attribute host.
8 9 10 |
# File 'lib/couchrest/database.rb', line 8 def host @host end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
8 9 10 |
# File 'lib/couchrest/database.rb', line 8 def name @name end |
#root ⇒ Object (readonly)
Returns the value of attribute root.
8 9 10 |
# File 'lib/couchrest/database.rb', line 8 def root @root end |
#server ⇒ Object (readonly)
Returns the value of attribute server.
8 9 10 |
# File 'lib/couchrest/database.rb', line 8 def server @server end |
#uri ⇒ Object (readonly)
Returns the value of attribute uri.
8 9 10 |
# File 'lib/couchrest/database.rb', line 8 def uri @uri end |
Instance Method Details
#batch_save_doc(doc) ⇒ Object
Save a document to CouchDB in batch mode. See #save_doc’s batch
argument.
205 206 207 |
# File 'lib/couchrest/database.rb', line 205 def batch_save_doc(doc) save_doc(doc, false, true) end |
#bulk_save(docs = nil, use_uuids = true) ⇒ Object Also known as: bulk_delete
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.
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/couchrest/database.rb', line 213 def bulk_save(docs = nil, use_uuids = true) 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 CouchRest.post "#{@root}/_bulk_docs", {:docs => docs} end |
#bulk_save_doc(doc) ⇒ Object
Save a document to CouchDB in bulk mode. See #save_doc’s bulk
argument.
200 201 202 |
# File 'lib/couchrest/database.rb', line 200 def bulk_save_doc(doc) save_doc(doc, true) end |
#compact! ⇒ Object
Compact the database, removing old document revisions and optimizing space use.
288 289 290 |
# File 'lib/couchrest/database.rb', line 288 def compact! CouchRest.post "#{@root}/_compact" end |
#copy_doc(doc, dest) ⇒ Object
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
249 250 251 252 253 254 255 256 257 258 |
# File 'lib/couchrest/database.rb', line 249 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! ⇒ Object
Create the database
293 294 295 296 |
# File 'lib/couchrest/database.rb', line 293 def create! bool = server.create_db(@name) rescue false bool && true end |
#delete! ⇒ Object
DELETE the database itself. This is not undoable and could be rather catastrophic. Use with care!
319 320 321 |
# File 'lib/couchrest/database.rb', line 319 def delete! CouchRest.delete @root end |
#delete_attachment(doc, name, force = false) ⇒ Object
DELETE an attachment directly from CouchDB
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/couchrest/database.rb', line 123 def (doc, name, force=false) uri = (doc, name) # this needs a rev begin CouchRest.delete(uri) rescue Exception => error if force # get over a 409 doc = get(doc['_id']) uri = (doc, name) CouchRest.delete(uri) else error end end end |
#delete_doc(doc, bulk = false) ⇒ Object
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.
235 236 237 238 239 240 241 242 243 244 |
# File 'lib/couchrest/database.rb', line 235 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 |
#documents(params = {}) ⇒ Object
Query the _all_docs
view. Accepts all the same arguments as view.
40 41 42 43 44 45 46 47 48 |
# File 'lib/couchrest/database.rb', line 40 def documents(params = {}) keys = params.delete(:keys) url = CouchRest.paramify_url "#{@root}/_all_docs", params if keys CouchRest.post(url, {:keys => keys}) else CouchRest.get url end end |
#fetch_attachment(doc, name) ⇒ Object
GET an attachment directly from CouchDB
111 112 113 114 |
# File 'lib/couchrest/database.rb', line 111 def (doc, name) uri = (doc, name) RestClient.get uri, CouchRest.default_headers end |
#get(id, params = {}) ⇒ Object
GET a document from CouchDB, by id. Returns a Ruby Hash.
96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/couchrest/database.rb', line 96 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 |
#get_bulk(ids) ⇒ Object Also known as: bulk_load
load a set of documents by passing an array of ids
58 59 60 |
# File 'lib/couchrest/database.rb', line 58 def get_bulk(ids) documents(:keys => ids, :include_docs => true) end |
#info ⇒ Object
GET the database info from CouchDB
35 36 37 |
# File 'lib/couchrest/database.rb', line 35 def info CouchRest.get @root end |
#put_attachment(doc, name, file, options = {}) ⇒ Object
PUT an attachment directly to CouchDB
117 118 119 120 |
# File 'lib/couchrest/database.rb', line 117 def (doc, name, file, = {}) uri = (doc, name) JSON.parse(RestClient.put(uri, file, CouchRest.default_headers.merge())) end |
#recreate! ⇒ Object
Delete and re create the database
299 300 301 302 303 304 305 |
# File 'lib/couchrest/database.rb', line 299 def recreate! delete! create! rescue RestClient::ResourceNotFound ensure create! end |
#replicate_from(other_db, continuous = false, create_target = false) ⇒ Object
Replicates via “pulling” from another database to this database. Makes no attempt to deal with conflicts.
308 309 310 |
# File 'lib/couchrest/database.rb', line 308 def replicate_from(other_db, continuous = false, create_target = false) replicate(other_db, continuous, :target => name, :create_target => create_target) end |
#replicate_to(other_db, continuous = false, create_target = false) ⇒ Object
Replicates via “pushing” to another database. Makes no attempt to deal with conflicts.
313 314 315 |
# File 'lib/couchrest/database.rb', line 313 def replicate_to(other_db, continuous = false, create_target = false) replicate(other_db, continuous, :source => name, :create_target => create_target) end |
#save_doc(doc, bulk = false, batch = false) ⇒ Object
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.”
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/couchrest/database.rb', line 161 def save_doc(doc, bulk = false, batch = false) if doc['_attachments'] doc['_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 |
#search(name, params = {}) ⇒ Object
Query a CouchDB-Lucene search view
51 52 53 54 55 |
# File 'lib/couchrest/database.rb', line 51 def search(name, params={}) # -> http://localhost:5984/yourdb/_fti/YourDesign/by_name?include_docs=true&q=plop*' url = CouchRest.paramify_url "#{root}/_fti/#{name}", params CouchRest.get url end |
#slow_view(funcs, params = {}) ⇒ Object Also known as: temp_view
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.
66 67 68 69 70 71 |
# File 'lib/couchrest/database.rb', line 66 def slow_view(funcs, params = {}) keys = params.delete(:keys) funcs = funcs.merge({:keys => keys}) if keys url = CouchRest.paramify_url "#{@root}/_temp_view", params JSON.parse(RestClient.post(url, funcs.to_json, CouchRest.default_headers)) end |
#to_s ⇒ Object
returns the database’s uri
30 31 32 |
# File 'lib/couchrest/database.rb', line 30 def to_s @root end |
#update_doc(doc_id, params = {}, update_limit = 10) ⇒ Object
Updates the given doc by yielding the current state of the doc and trying to update update_limit times. Returns the new doc if the doc was successfully updated without hitting the limit
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 |
# File 'lib/couchrest/database.rb', line 263 def update_doc(doc_id, params = {}, update_limit=10) resp = {'ok' => false} new_doc = nil last_fail = nil until resp['ok'] or update_limit <= 0 doc = self.get(doc_id, params) # grab the doc new_doc = yield doc # give it to the caller to be updated begin resp = self.save_doc new_doc # try to PUT the updated doc into the db rescue RestClient::RequestFailed => e if e.http_code == 409 # Update collision update_limit -= 1 last_fail = e else # some other error raise e end end end raise last_fail unless resp['ok'] new_doc end |
#view(name, params = {}, &block) ⇒ Object
Query a CouchDB view as defined by a _design
document. Accepts paramaters as described in wiki.apache.org/couchdb/HttpViewApi
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/couchrest/database.rb', line 78 def view(name, params = {}, &block) keys = params.delete(:keys) name = name.split('/') # I think this will always be length == 2, but maybe not... dname = name.shift vname = name.join('/') url = CouchRest.paramify_url "#{@root}/_design/#{dname}/_view/#{vname}", params if keys CouchRest.post(url, {:keys => keys}) else if block_given? @streamer.view("_design/#{dname}/_view/#{vname}", params, &block) else CouchRest.get url end end end |