Class: CouchRest::Database
- Inherits:
-
Object
- Object
- CouchRest::Database
- Defined in:
- lib/couchrest/database.rb
Instance Attribute Summary collapse
-
#bulk_save_cache_limit ⇒ Object
How many documents should be cached before peforming the bulk save operation.
-
#name ⇒ Object
readonly
Name of the database of we’re using.
-
#path ⇒ Object
readonly
Name of the database we can use in requests.
-
#server ⇒ Object
readonly
Server object we’ll use to communicate with.
Instance Method Summary collapse
-
#all_docs(params = {}, payload = {}, &block) ⇒ Object
(also: #documents)
Query the
_all_docs
view. -
#batch_save_doc(doc) ⇒ Object
Save a document to CouchDB in batch mode.
-
#bulk_save(docs = nil, opts = {}) ⇒ Object
(also: #bulk_delete)
POST an array of documents to CouchDB.
-
#bulk_save_doc(doc) ⇒ Object
Save a document to CouchDB in bulk mode.
-
#changes(params = {}, payload = {}, &block) ⇒ Object
Query CouchDB’s special
_changes
feed for the latest. -
#compact! ⇒ Object
Compact the database, removing old document revisions and optimizing space use.
- #connection ⇒ Object
-
#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
. -
#fetch_attachment(doc, name) ⇒ Object
GET an attachment directly from CouchDB.
-
#fti(name, params = {}) ⇒ Object
(also: #search)
Query a CouchDB-Lucene search view.
-
#get(*args) ⇒ Object
GET the requested document by ID like ‘get!`, but returns nil if the document does not exist.
-
#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, expects an IO object, or a string that will be converted to a StringIO in the ‘file’ parameter.
-
#recreate! ⇒ Object
Delete and re create the database.
-
#replicate_from(other_db, continuous = false, create_target = false, doc_ids = nil) ⇒ Object
Replicates via “pulling” from another database to this database.
-
#replicate_to(other_db, continuous = false, create_target = false, doc_ids = nil) ⇒ Object
Replicates via “pushing” to another database.
-
#save_doc(doc, bulk = false, batch = false) ⇒ Object
Save a document to CouchDB.
-
#temp_view(payload, params = {}, &block) ⇒ Object
(also: #slow_view)
POST a temporary view function to CouchDB for querying.
-
#to_s ⇒ Object
String of #root.
-
#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.
-
#uri ⇒ Object
(also: #root)
A URI object for the exact location of this database.
-
#view(name, params = {}, payload = {}, &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
26 27 28 29 30 31 32 |
# File 'lib/couchrest/database.rb', line 26 def initialize(server, name) @name = name @server = server @path = "/#{CGI.escape(name)}" @bulk_save_cache = [] @bulk_save_cache_limit = 500 # must be smaller than the uuid count end |
Instance Attribute Details
#bulk_save_cache_limit ⇒ Object
How many documents should be cached before peforming the bulk save operation
17 18 19 |
# File 'lib/couchrest/database.rb', line 17 def bulk_save_cache_limit @bulk_save_cache_limit end |
#name ⇒ Object (readonly)
Name of the database of we’re using.
11 12 13 |
# File 'lib/couchrest/database.rb', line 11 def name @name end |
#path ⇒ Object (readonly)
Name of the database we can use in requests.
14 15 16 |
# File 'lib/couchrest/database.rb', line 14 def path @path end |
#server ⇒ Object (readonly)
Server object we’ll use to communicate with.
8 9 10 |
# File 'lib/couchrest/database.rb', line 8 def server @server end |
Instance Method Details
#all_docs(params = {}, payload = {}, &block) ⇒ Object Also known as: documents
Query the _all_docs
view. Accepts all the same arguments as view.
303 304 305 |
# File 'lib/couchrest/database.rb', line 303 def all_docs(params = {}, payload = {}, &block) view("_all_docs", params, payload, &block) end |
#batch_save_doc(doc) ⇒ Object
Save a document to CouchDB in batch mode. See #save_doc’s batch
argument.
179 180 181 |
# File 'lib/couchrest/database.rb', line 179 def batch_save_doc(doc) save_doc(doc, false, true) end |
#bulk_save(docs = nil, opts = {}) ⇒ 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.
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/couchrest/database.rb', line 187 def bulk_save(docs = nil, opts = {}) opts = { :use_uuids => true, :all_or_nothing => false }.update(opts) if docs.nil? docs = @bulk_save_cache @bulk_save_cache = [] end if opts[: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 opts[:all_or_nothing] request_body[:all_or_nothing] = true end results = connection.post "#{path}/_bulk_docs", request_body docs_by_id = Hash[docs.map { |doc| [doc['_id'], doc] }] unless docs.nil? results.each { |r| docs_by_id[r['id']]['_rev'] = r['rev'] if r['ok'] } unless results.nil? results end |
#bulk_save_doc(doc) ⇒ Object
Save a document to CouchDB in bulk mode. See #save_doc’s bulk
argument.
174 175 176 |
# File 'lib/couchrest/database.rb', line 174 def bulk_save_doc(doc) save_doc(doc, true) end |
#changes(params = {}, payload = {}, &block) ⇒ Object
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.
314 315 316 |
# File 'lib/couchrest/database.rb', line 314 def changes(params = {}, payload = {}, &block) view("_changes", params, payload, &block) end |
#compact! ⇒ Object
Compact the database, removing old document revisions and optimizing space use.
55 56 57 |
# File 'lib/couchrest/database.rb', line 55 def compact! connection.post "#{path}/_compact" end |
#connection ⇒ Object
34 35 36 |
# File 'lib/couchrest/database.rb', line 34 def connection server.connection 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
231 232 233 234 235 236 237 238 239 240 |
# File 'lib/couchrest/database.rb', line 231 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 connection.copy "#{path}/#{slug}", destination end |
#create! ⇒ Object
Create the database
60 61 62 63 |
# File 'lib/couchrest/database.rb', line 60 def create! bool = server.create_db(path) rescue false bool && true end |
#delete! ⇒ Object
DELETE the database itself. This is not undoable and could be rather catastrophic. Use with care!
86 87 88 |
# File 'lib/couchrest/database.rb', line 86 def delete! connection.delete path end |
#delete_attachment(doc, name, force = false) ⇒ Object
DELETE an attachment directly from CouchDB
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 |
# File 'lib/couchrest/database.rb', line 347 def (doc, name, force=false) attach_path = (doc, name) begin connection.delete(attach_path) rescue Exception => error if force # get over a 409 doc = get(doc['_id']) attach_path = (doc, name) connection.delete(attach_path) 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.
217 218 219 220 221 222 223 224 225 226 |
# File 'lib/couchrest/database.rb', line 217 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']) connection.delete "#{path}/#{slug}?rev=#{doc['_rev']}" end |
#fetch_attachment(doc, name) ⇒ Object
GET an attachment directly from CouchDB
335 336 337 |
# File 'lib/couchrest/database.rb', line 335 def (doc, name) connection.get (doc, name), :raw => true end |
#fti(name, params = {}) ⇒ Object Also known as: search
Query a CouchDB-Lucene search view
319 320 321 322 |
# File 'lib/couchrest/database.rb', line 319 def fti(name, params={}) # -> http://localhost:5984/yourdb/_fti/YourDesign/by_name?include_docs=true&q=plop*' view("_fti/#{name}", params) end |
#get(*args) ⇒ Object
GET the requested document by ID like ‘get!`, but returns nil if the document does not exist.
111 112 113 114 115 |
# File 'lib/couchrest/database.rb', line 111 def get(*args) get!(*args) rescue CouchRest::NotFound nil end |
#get!(id, params = {}) ⇒ Object
GET a document from CouchDB, by id. Returns a Document, Design, or raises an exception if the document does not exist.
95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/couchrest/database.rb', line 95 def get!(id, params = {}) slug = escape_docid(id) url = CouchRest.paramify_url("#{path}/#{slug}", params) result = connection.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
326 327 328 |
# File 'lib/couchrest/database.rb', line 326 def get_bulk(ids) all_docs(:keys => ids, :include_docs => true) end |
#info ⇒ Object
GET the database info from CouchDB
50 51 52 |
# File 'lib/couchrest/database.rb', line 50 def info connection.get path end |
#put_attachment(doc, name, file, options = {}) ⇒ Object
PUT an attachment directly to CouchDB, expects an IO object, or a string that will be converted to a StringIO in the ‘file’ parameter.
341 342 343 344 |
# File 'lib/couchrest/database.rb', line 341 def (doc, name, file, = {}) file = StringIO.new(file) if file.is_a?(String) connection.put (doc, name), file, end |
#recreate! ⇒ Object
Delete and re create the database
66 67 68 69 70 71 72 |
# File 'lib/couchrest/database.rb', line 66 def recreate! delete! create! rescue CouchRest::NotFound ensure create! end |
#replicate_from(other_db, continuous = false, create_target = false, doc_ids = nil) ⇒ Object
Replicates via “pulling” from another database to this database. Makes no attempt to deal with conflicts.
75 76 77 |
# File 'lib/couchrest/database.rb', line 75 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 |
#replicate_to(other_db, continuous = false, create_target = false, doc_ids = nil) ⇒ Object
Replicates via “pushing” to another database. Makes no attempt to deal with conflicts.
80 81 82 |
# File 'lib/couchrest/database.rb', line 80 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_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.”
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/couchrest/database.rb', line 138 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 doc_path = "#{path}/#{slug}" doc_path << "?batch=ok" if batch connection.put doc_path, doc rescue CouchRest::NotFound puts "resource not found when saving even though an id was passed" slug = doc['_id'] = server.next_uuid connection.put "#{path}/#{slug}", doc end else slug = doc['_id'] = @server.next_uuid connection.put "#{path}/#{slug}", doc end if result['ok'] doc['_id'] = result['id'] doc['_rev'] = result['rev'] doc.database = self if doc.respond_to?(:database=) end result end |
#temp_view(payload, params = {}, &block) ⇒ Object Also known as: slow_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.
296 297 298 |
# File 'lib/couchrest/database.rb', line 296 def temp_view(payload, params = {}, &block) view('_temp_view', params, payload, &block) end |
#to_s ⇒ Object
String of #root
45 46 47 |
# File 'lib/couchrest/database.rb', line 45 def to_s uri.to_s 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 doc if successfully updated without hitting the limit. If the limit is reached, the last execption will be raised.
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
# File 'lib/couchrest/database.rb', line 246 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 CouchRest::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 |
#uri ⇒ Object Also known as: root
A URI object for the exact location of this database
39 40 41 |
# File 'lib/couchrest/database.rb', line 39 def uri server.uri + path end |
#view(name, params = {}, payload = {}, &block) ⇒ Object
Query a CouchDB view as defined by a _design
document. Accepts paramaters as described in wiki.apache.org/couchdb/HttpViewApi
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 |
# File 'lib/couchrest/database.rb', line 274 def view(name, params = {}, payload = {}, &block) opts = {} params = params.dup payload['keys'] = params.delete(:keys) if params[:keys] # Continuous feeds need to be parsed differently opts[:continuous] = true if params['feed'] == 'continuous' # Try recognising the name, otherwise assume already prepared view_path = name_to_view_path(name) req_path = CouchRest.paramify_url("#{path}/#{view_path}", params) if payload.empty? connection.get req_path, opts, &block else connection.post req_path, payload, opts, &block end end |